一:机制与策略(转)
http://www.51hei.com/bbs/dpj-29441-1.html
机制mechanism,策略policy。如果你看过《linux device drivers》,里面给出了大概的介绍。机制提供了干什么(do what),策略提供如何做(how to do)。驱动程序完成机制的功能,把策略的实现留给用户的应用程序。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二:用户空间和内核空间
一个模块在内核空间运行, 而应用程序在用户空间运行. 这个概念是操作系统理论的基础,
驱动模块试涉及到内核态以及用户态,当应用程序发出一个systerm call或者被硬件的中断挂起,内核在上下文中执行systerm call(系统调用),内核和应用程序的memory map也不同,所以
内核的内存空间以及应用程序的内存空间不能互相访问,要用到copy_to_user 以及copy_from_user函数;
内核程序与应用程序最大的不同是内核是并发的,而应用程序是按顺序执行的;所以应用程序不用担心上线文切换,而内核必须要做好上下文切换;
2.6内核以后,内核是抢占式的,这必须要求内核代码是可重入的
内核的栈是非常小的,内核共用4k的栈,所以当需要大的结构体时,是使用堆内存;kzalloc
驱动模块的代码中的函数以及数据结构跟内核的版本紧密相连,所以编译模块的时候要选用正确的内核版本,安装模块的时候也要选择正确的内核版本;
如果
2.6 预备知识
#include <linux/module.h> 包含大量的模块加载卸载的头文件 如module_init 、module_exit等函数
#include <linux/init.h> 指定清理的初始化函数,init的初始化函数
MODULE_LICENSE("GPL"); 内核认识的特定许可有, "GPL"( 适用 GNU 通用公共许可的任何版本 ),
MODULE_AUTHOR ( 声明谁编写了模块 ),
MODULE_DESCRIPION( 一个人可读的关于模块做什么的声明 ),
MODULE_VERSION ( 一个代码修订版本号
MODULE_ALIAS ( 模块为人所知的另一个名子 )
以及 MODULE_DEVICE_TABLE ( 来告知用户空间, 模块支持那些设备 ).
2.7 初始化中的错误处理
这点很重要,比如你在insmodu 一个模块的时候加载失败,如果这个驱动模块的代码没有进行相关错误处理,在加载会出现更多问题
错误恢复是最好使用goto语句;
1 int __init my_init_function(void) 2 { 3 int err; 4 err = register_this(ptr1, "skull"); /* registration takes a pointer and a name */
5 if (err) 6 goto fail_this; 7 err = register_that(ptr2, "skull"); 8 if (err) 9 goto fail_that; 10 err = register_those(ptr3, "skull"); 11 if (err) 12 goto fail_those; 13 return 0; /* success */
14 fail_those: 15 unregister_that(ptr2, "skull"); 16 fail_that: 17 unregister_this(ptr1, "skull"); 18 fail_this: 19 return err; /* propagate the error */
20 }
或者在失败的时候直接执行你的清理函数即可,但是这样需要更多的上下文切换,消耗更过的内存空间,寄存器等;或者可以下下面一个函数;
检查每种操作的状态,在清理,但是这样做的坏处是需要定义很多歌变量,还是用goto比较好;
1 struct something *item1; 2 struct somethingelse *item2; 3 int stuff_ok; 4 void my_cleanup(void) 5 { 6 if (item1) 7 release_thing(item1); 8 if (item2) 9 release_thing2(item2); 10 if (stuff_ok) 11 unregister_stuff(); 12 return; 13 }
1 int __init my_init(void) 2 { 3 int err = -ENOMEM; 4 item1 = allocate_thing(arguments); 5 item2 = allocate_thing2(arguments2); 6 if (!item2 || !item2) 7 goto fail; 8 err = register_stuff(item1, item2); 9 if (!err) 10 stuff_ok = 1; 11 else
12 goto fail; 13 return 0; /* success */
14 fail: 15 my_cleanup(); 16 return err; 17 }