`
java-mans
  • 浏览: 11390773 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

设置测试系统开发环境及Hello World入门模块在前面博文中已经讲到,请参考http://blog.csdn.net/tianshuai11/article/details/7442168

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

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

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

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

二,用户空间和内核空间

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

每当应用程序执行系统调用或者被硬件中断挂起时,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修改了,那么你的模块看到的参数值也被修改了,但是你的模块不会收到任何通知;你应当不要使模块参数可写,除非你准备好检测这个改变并因而作出反应;
<wbr></wbr>

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

用户空间驱动程序的优点:
1)可以和整个C库链接
2)驱动程序不用借助外部程序(对于复杂的外设,常常需要和驱动一起发行用户提供策略的应用程序)就可以完成许多非常规的任务。
3)在驱动中可以使用浮点数,在某些特殊的硬件中,可能需要使用浮点数,而linux内核并不提供浮点数的支持。如果能在用户态实现驱动,就可以轻松解决这一问题
4) 驱动的问题不会导致整个系统挂起,有过驱动开发经验的人一定会对调试深有感触,一些错误常常导致整个系统挂起。而用户态的驱动在调试上就要方便很多。
5) 用户内存可以换出
6)设计良好的驱动仍然可以支持对设备的并发访问
7)可以给出封闭源码的驱动程序,不必采用GPL,更为灵活


用户空间驱动的最常见例子是X-server,很多USB设备的驱动也可以放到用户空间。目前,很多人尝试在用户态为PCI设备提供驱动

用户空间驱动的缺点:
1)中断在用户空间不可用,最新的UIO接口已经解决了这一问题
2)响应时间较慢
3)只能支持字符设备,无法支持块设备和网络设备
4)可靠性较低,很多驱动都是闭源的,我们没法通过阅读代码解决问题
5)有些硬件厂商只提供和某些linux开发版(常常早就过时了)相匹配的用户空间驱动















分享到:
评论

相关推荐

    LINUX设备驱动第三版_588及代码.rar

    第二章 构造和运行模块 设置测试系统 Hello World模块 核心模块与应用程序的对比 编译和装载 内核符号表 预备知识 初始化和关闭 模块参数 在用户空间编写驱动程序 快速参考 第三章 字符设备驱动程序 ...

    linux设备驱动程序

    第二章 构造和运行模块 设置测试系统 Hello world模块 核心模块与应用程序的对比 编译和装载 内核符号表 预备知识 初始化和关闭 模块参数 在用户空间编写驱动程序 快速参考 ch03.第三章 字符设备驱动程序 scull的...

    linux驱动学习去开发入门

    Linux设备驱动程序学习(0)-Hello, world!模块 Linux设备驱动程序学习(0) -Hello, world!模块 ...以上就是我对《Linux设备驱动程序(第3版)》的《第二章 构造和运行模块》 的学习总结

    Linux DeviceDrivers 3rd Edition

    第二章 构造和运行模块 21 设置测试系统 21 Hello World模块 22 核心模块与应用程序的对比 24 编译和装载 28 内核符号表 33 预备知识 35 初始化和关闭 36 模块参数 40 在用户空间编写驱动程序 42 .快速...

    嵌入式Linux C编程入门(第2版) PPT

    第12章 嵌入式linux设备驱动开发 355 12.1 设备驱动概述 355 12.1.1 设备驱动简介 355 12.1.2 设备驱动程序的特点 356 12.2 模块编程 357 12.2.1 模块编程简介 357 12.2.2 模块相关命令 357 ...

    RED HAT LINUX 6大全

    第1章 Red Hat Linux和UNIX简介 1 1.1 Linux的优点 2 1.2 版权和保证 3 1.3 在哪里可以获取Red Hat Linux 3 1.4 系统需求 3 1.5 小结 4 第2章 Red Hat系统的安装 5 2.1 准备,认真准备 5 2.2 安装Red Hat Linux 6 ...

    python入门到高级全栈工程师培训 第3期 附课件代码

    第1章 01 计算机发展史 02 计算机系统 03 小结 04 数据的概念 05 进制转换 06 原码补码反码 07 物理层和数据链路层 08 网络层和arp协议 09 传输层和应用层 第2章 01 上节课复习 02 arp协议复习 03 字符编码 第3...

Global site tag (gtag.js) - Google Analytics