曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 8909|回复: 0
打印 上一主题 下一主题

模块参数|内核变量

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-8-30 16:09:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
设备驱动程序通常使用固定的内部变量值,而由源代码指定该变量。根据具体情况,还可在运行设备驱动程序之前修改变量。如在 linux系统启动时,在选择系统菜单的下方可以看到视频参数的设置 ---这类参数属于初始化变量,可在加载或卸载模块时进行修改。通常利用 bootloader 的选项功能或模块的实用程序 insmod 命令调整为内核命令模式。

设备驱动程序的初始化参数中外部能够修改的变量称作模块变量。设备驱动程序创建为模块后,利用以下 insmod 命令可以指定变量:
insmod ./test.ko onevalue=0x27 twostring="Oh my god!"

由 insmod 命令指定模块变量,而模块插入内核时处理该变量。

2.4 内核中使用模块变量实例
#include <linux/module.h>
#include <linux/kernel.h>

static int onevalue = 1;
static char *twostring = NULL;

MODULE_PARM (onevalue, "i");
MODULE_PARM (twostring, "s");

int init_module (void)
{
        printk ("Hello world [onevalue=%d:twostring=%s]\n", onevalue, twostring);
        return 0;
}

void cleanup_module (void)
{
        printk ("Goodbye world\n");
}
由于本机是基于 2.6 内核的 opensuse11.1 ,所以 2.4 内核环境选择在华恒的一块开发板上做这个测试。对于这个程序,直接在命令行里编译:
beyes@linux-beyes:~/C/hh2410/module_test> /opt/host/armv4l/bin/armv4l-unknown-linux-gcc -D__KERNEL__ -DMODULE -Wall -O2 -I/HHARM2410-STUDY/kernel/include/ -c test.c -o test.o
编译后,把 test.o 所在文件夹通过 NFS 服务器共享出去,然后通过 minicom 连接到开发板,接着在开发板上把文件拷贝到根目录,然后执行:
insmod test.o onevalue=0x27 twostring="Oh my god"
用 dmesg 看到输出:
Hello world [onevalue=39:twostring]=Oh my god
说明
MODULE_PARM 宏的语法如下:
MODULE_PARM (变量名, 变量类型) 扩展
[变量类型]
      b:byte
      h:short
      i : int
      l : long
      s : string
MODULE_PARM 宏不能定义变量,所以如果需要这个宏来传递命令行参数,那么就需要在模块中定义一个全局变量。在 insmod 模块时,就可以使用参数的形式,将具体的实参传递给模块中的那个全局变量。MODULE_PARM(name, type)的两个参数,一个是全局变量的名称,另一个就是上面所示的变量类型。

在传递字符串类型的参数时,全局变量需要在模块中使用 char * 来声明,insmod 会自动为其分配内存空间。

MODULE_PARM() 也支持数组类型。用短线 '-' 把两个数字分开,分别表示数组中的最小位数和最大位数。比如:
int a[5];
MODULE_PARM(a,  "1-5i");

2.6 内核模块变量使用实例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>

static int onevalue = 1;
static char *twostring = NULL;

module_param (onevalue, int, 0);
module_param (twostring, charp, 0);

static int hello_init (void)
{
    printk ("Hello, world [onevalue=%d:twostring=%s]\n", onevalue, twostring);
    return 0;
}

static void hello_exit (void)
{
    printk ("Goodbye, world\n");
}

module_init (hello_init);
module_exit (hello_exit);

MODULE_LICENSE ("Dual BSD/GPL");
编译后,加载到内核并随即卸载:
beyes@linux-beyes:~/C/hh2410/module_test> sudo /sbin/insmod test26.ko onevalue=0x27 twostring="hello,baby"
beyes@linux-beyes:~/C/hh2410/module_test> sudo /sbin/rmmod test26.ko
注意,在 2.6 内核中,字符串参数不能有空格,否则出错!如:
beyes@linux-beyes:~/C/hh2410/module_test> sudo /sbin/insmod test26.ko onevalue=0x27 twostring="hello baby"
insmod: error inserting 'test26.ko': -1 Unknown symbol in module
查看内核输出信息
Hello, world [onevalue=39:twostring=hello,baby]
Goodbye, world

............. ................ .............. ............... ............. ...................
与 2.4 内核不同,2.6 内核中使用模块变量时应包含 linux/moduleparam.h 头文件。
2.6 内核中用 module_param 宏代替 2.4 内核中使用过的 MODULE_PARM 宏。

module_param 宏语法格式:
module_param (变量名, 变量类型, 使用属性)
[变量类型]
      short: short
      ushort: unsigned short
      int: int
      unit: unsigned int
      long: long
      ulong:unsigned long
      charp: char*
      bool: int
      invbool: int
      intarray: int*
[使用属性]
除了特殊情况,通常把文件结点属性指定为 0。该参数用来设置用户的访问权限,普通用户能在内核上加载模块的几率很少。如果一定要设置结点,可用文件权限 (permission) 等概念指定 0644 等八进制数。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 13:23 , Processed in 0.111737 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表