当前进程:
内核代码可以通过访问全局项 currert 来获得当前进程。在文件 中定义,是一个指向task_struct 的指针。task_struct 结构在 中定义。在2.6 内核中,内核开发者将指向 task_struct 结构的指针隐藏在 内核栈中,这对内核其它子系统隐藏,设备驱动程序只要包含即可引用当前进程。例:
printk(KERN_INFO " The process is \"%s"\(pid %i)\n"),current->comm,current->pid);
初始化和关闭:
static int __int initialization_function(void)
{
/*初始化到的代码*/
}
module_init(initialization_function)
__init 对内核来讲是一种暗示,表明该函数仅在初始化时使用。在模块被装载之后,模块装载器就会将初始化函数扔掉,将该函数的占用的内存释放出来
__init __initdata 的使用是可选的,虽然有点繁琐,但是有时候很值得使用。
__devinit __devinitdata 只有在内核未被配置为支持热插拔设备的情况下,这两个标记才会被翻译为 __init __initdata
struct void __exit cleanup_function(void)
{
codes;
}
module_exit(cleaup_function)
该函数在模块被移除之前注销借口并向系统返回所有的资源,如果内核的配置不允许模块被卸载或者模块直接被嵌套在内核中,则被标记为 __exit 的函数将会被简单的丢弃。
# 初始化出错后的处理:……
int __init my_init_function(void)
{
int err;
err=register_this(ptr1,"skull");
ir(err) goto fail_this;
err=register_that(ptr2,"skull");
if(err) goto fail_that;
err=register_those(ptr3,"skull");
if(err) goto fail_those;
return 0;
fail_those : unregister_that();
fail_that : unregister_this();
fail_this : return err;
}
模块的装载与竞争: 在初始化还在运行的时候,内核就完全可能会调用嗯我们的模块,因此在首次注册完成之后,代码就应该准备好被内核的其他部分调用,在用来支持某个设施的所有的内部初始化完成之前,不要注册任何设备。我们不应该让这种情况发生:我们的模块初始化失败,但此时内核已经部分使用了我们的模块注册的设备,这种情况我们应该仔细处理内核和其他部分的正在进行的操作。(P40)
模块参数:
内核允许对驱动程序指定参数,而这些参数可以在装载驱动程序时改变,这些参数必须用moudle_param 宏使这些参数对 insmod 可见:
module_param(name , type , perm);
其中 type 可以是:
bool
invbool
布尔值(true 或 faule ) 关联的变量应该是 int 型 。invbool 类型取其反值,即 true 变为 faule ,faule 变为 true 。
charp
字符类型的指针,内核会为用户的提供的字符传分配内存,并相应的设置其值。
int
long
short
uint
ulong
ushort
具有不同长度的基本整数值,以u 开头表示为 无符号型。
module_param_array(name , type ,num ,perm);
向内核声明一个名字为 name , 大小为 num 的 type 类型的数组,模块装载器会拒绝接受超过 num(数组的大小) 大小的值。
perm : 访问许可值,这个值用开控制谁能够访问sysfs中对模块参数的表述。如果perm 为 0 ,则不会有对应的 sysfs 入口项。否则
为: S_IRUGO, 任何人可以读取该参数,但不能修改,S_IRUGO|S_IWUSR 允许root 用户修改该参数。注意,若果一个参数通过sysfs而被修改,则如同模块修改了该参数一样,但内核不会以任何方式通知模块该参数被修改,所以,大多数情况下我们不应让模块参数是可写的。
实例代码:
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
//static char *whom = "world" ;
//static int howmany = 3 ;
static char *whom ;
static int howmany ;
module_param(whom, charp ,S_IRUGO);
module_param(howmany , int ,S_IRUGO);
static int param_init(void)
{
int i ;
for(i=0;i
printk(KERN_INFO "Hello , %s \n",whom);
}
return 0;
}
static void param_exit(void)
{
printk(KERN_INFO " GOODBYE \n");
}
module_init(param_init);
module_exit(param_exit);
该程序在内核中打印 howmany 次 *whom ;例如:
在装入模块时 : sudo insmod param.ko howmany=10 whom="world" 在内核中打印 10 次 Hello ,World
在终端下输入: dmesg 查看模块的输出:
[ 6837.794661] Hello , World
[ 6837.794668] Hello , World
[ 6837.794672] Hello , World
[ 6837.794676] Hello , World
[ 6837.794679] Hello , World
[ 6837.794683] Hello , World
[ 6837.794687] Hello , World
[ 6837.794690] Hello , World
[ 6837.794694] Hello , World
[ 6837.794697] Hello , World