【Linux 驱动】第二章 构造和运行模块

设置测试系统开发环境及Hello World入门模块在前面中已经讲到,请参考:

一,核心模块与应用程序的对比

应用程序:小规模及中规模程序,从头到尾执行单个任务。

核心模块:预先注册自己,以便服务于将来的某个请求。然后他的初始化函数就立即结束。

退出时候,应用程序可以不释放自己申请的资源,而模块在退出之前必须仔细撤销初始化函数所做的一切。

二,用户空间和内核空间

模块运行在内核空间,应用程序运行在内核空间。

每当应用程序执行系统调用或者被硬件中断挂起时,Unix将执行模式从用户空间切换到内核空间。

应用程序在虚拟内存中布局,并具有一块很大的栈空间(保存函数调用历史以及当前活动函数中的自动变量)。内核具有非常小的栈,所以我们自己的函数必须和整个内核空间调用链一同共享这个栈。

【注意】在内核API中看到有两个下划线_ _的函数名:接口的底层组件

三,初始化和关闭

static  int  _ _init  initialization_function(void)

{

/*初始化代码*/

return <int>;


           }

module_init(initialization_function); //说明内核初始化位置,没有这个函数,则初始化函数无法调用


【注意】_ _init    _ _initdata表明函数只在初始化期间使用,模块装载完成后不再使用。


    static  void  _ _init  cleanup_function(void)//没有返回值

清除函数 类似 module_exit(cleanup_function)

四,初始化过程中的错误处理

1)时刻铭记,注册可能会失败,因此模块代码要始终检查返回值。

2)当注册时,有些模块注册失败,则需要自行撤销已注册的设施。否则内核处于一种不稳定状态。唯一有效的解决办法:重新引导系统

3)使用goto

int  _ _my_init_function(void)

{

int err;

err=regeister_this(ptr1,"skull");

if(err)  goto fail_this;

err=regeister_that(ptr2,"skull");

if(err)  goto fail_that;

err=regeister_those(ptr3,"skull");
                    if(err)  goto fail_those;


                     return 0;//成功


                   fail_this:return err;

fail_those:unregeister_those(ptr3,"skull");


                   fail_that:unregeister_that(ptr3,"skull");

}

4)初始化函数还在运行时,内核就完全可能会调用我们的模块。所以我们应在用来支持某个设施的所有内部初始化完成之前,不要注册任何设施。


五,模块参数支持很多类型;
    1)基本类型:
        bool   :布尔类型
        invbool:颠倒了值的bool类型;
        charp  :字符指针类型,内存为用户提供的字符串分配;
        int    :整型
        long   :长整型
        short  :短整型
        uint   :无符号整型
        ulong  :无符号长整型
        ushort :无符号短整型

定义模块参数的方法:
           module_param(name, type, perm);
     其中,name:表示参数的名字;
          type:表示参数的类型;
          perm:表示参数的访问权限;

2)数组类型:用逗号间隔的列表提供的值;
      声明一个数组参数:
           module_param_array(name, type, num, perm);
      其中,name:表示数组的名字;
           type:表示参数的类型;
           num :表示数组中元素数量;
           perm:表示参数的访问权限;
   3)参数的访问权限
       modlue_param和module_param_array中的perm用于设定该参数的访问权限;
       perm表示该参数在sysfs文件系统中所对应的文件节点的属性;你用该使用<linux/stat.h>中定义的权限值;这个值控制谁可以存取这些模块参数在sysfs文件系统中的表示;当perm为0时,表示此参数不存在sysfs文件系统下对应的文件节点;否则,模块被加载后,在/sys/module/目录下将会出现以此模块名命名的目录,带有给定的权限;
比如:
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
注意:如果一个参数被sysfs修改了,那么你的模块看到的参数值也被修改了,但是你的模块不会收到任何通知;你应当不要使模块参数可写,除非你准备好检测这个改变并因而作出反应;

六,在用户空间编写驱动程序

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://127.0.0.1/wyyxfy.html