Linux设备驱动程序学习(0)-Hello, world!模块

当linux环境已经搭建好,就准备开始下一步的学习,linux设备驱动和内核。计划按照LINUX设备驱动开发详解一书的顺序,一章一章学习。

一个学习Linux设备驱动程序都会碰到的第一个例程:
我将其复制到我的工作目录,并编写了一个简单的Makefile文件:
make以后产生helloworld.ko驱动。
[root@localhost helloworld]# ls
helloworld.c   helloworld.ko     helloworld.mod.o  Makefile   Module.symvers
helloworld.c~  helloworld.mod.c  helloworld.o      Makefile~
[root@localhost helloworld]#
[root@localhost helloworld]# insmod helloworld.ko
[root@localhost helloworld]# dmesg
 [<c04744e9>] sys_open+0x1c/0x1e
 [<c0404f70>] syscall_call+0x7/0xb
 =======================
Hello world
Goodbye, world
Hello world
Goodbye, world
Hello world
[root@localhost helloworld]#
有些心得,网友总结的很好,搬过来了。
学习心得:
(1)驱动模块运行在内核空间,运行时不能依赖于任何函数库和模块连接,所以在写驱动时所调用的函数只能是作为内核一部分的函数。
(2)驱动模块和应用程序的一个重要不同是:应用程序退出时可不管资源释放或者其他的清除工作,但模块的退出函数必须仔细撤销初始化函数所作的一切,否则,在系统重新引导之前某些东西就会残留在系统中。
(3)处理器的多种工作模式(级别)其实就是为了操作系统的用户空间和内核空间设计的。在Unix类的操作系统中只用到了两个级别:最高和最低级别。
(4)要十分注意驱动程序的并发处理。
(5)内核API中具有双下划线(_ _)的函数,通常是接口的底层组件,应慎用。
(6)
内核代码不能实现浮点书运算。

(7)Makefile文件分析:
(8)insmod使用公共内核符号表来解析模块中未定义的符号。公共内核符号表中包含了所有的全局内核项(即函数和变量 的地址 ),这是实现模块化驱动程序所必须的。
(9)Linux使用模块层叠技术,我们可以将模块划分为多个层,通过简化每个层可缩短开发周期。如果一个模块需要向其他模块到处符号,则使用下面的宏:
符号必须在模块文件的全局变量部分导出,因为这两个宏将被扩展为一个特殊变量的声明,而该变量必须是全局的。

(10)所有模块代码中都包含一下两个头文件:

(11)所有模块代码都 应该指定所使用的许可证:

MODULE_LICENSE("Dual BSD/GPL");


此外还有可选的其他描述性定义:

MODULE_AUTHOR("");
MODULE_DESCRIPTION("");
MODULE_VERSION("");
MODULE_ALIAS("");
MODULE_DEVICE_TABLE("");


上述
MODULE_ 声明习惯上放在文件最后。

(12)初始化和关闭
初始化的实际定义通常如下:

static int _ _init initialization_function(void)
{
/*初始化代码*/
}

module_init(initialization_function)


清除函数的实际定义通常如下:

static int _ _exit cleanup_function(void)
{
/*清除代码*/
}

module_exit(cleanup_function)


(13) Linux内核模块的初始化出错处理一般使用“goto”语句。通常情况下很少使用“goto”,但在出错处理是(可能是唯一的情况),它却非常有用。在大二学习C语言时,老师就建议不要使用“goto”,并说很少会用到。在这里也是我碰到的第一个建议使用“goto”的地方。在追求效率的代码中使用goto语句仍是最好的错误恢复机制。”-- 《Linux设备驱动程序(第3版)》 以下是 初始化出错处理的推荐代码示例:
(14)模块参数:内核允许对驱动程序指定参数,而这些参数可在装载驱动程序模块时改变
以下是我的实验程序:
实验结果是 :
我这个实验除了对参数的改变进行实验外,我的一个重要的目的是测试“ module_param_array(TNparam , int , &TNparam_nr , S_IRUGO);”中 &TNparam_nr对输入参数数目的限制作用。经过我的实验,表明 &TNparam_nr并没有对输入参数的数目起到限制作用。真正起到限制作用的是 static int TNparam[] = {1,2,3,4}; 本身定义的大小,我将程序进行修改:
static int TNparam[] = {1,2,3,4}; 
改为 static int TNparam[] = {1,2,3,4,5,6,7,8};
其他都不变。

编译后再进行实验,其结果是:

[Tekkaman2440@SBC2440V4]#insmod hello-param.ko howmany=2 whom="KeKe" TNparam=4,3,2,1,5,6,7,8
(0) Hello, KeKe !
(1) Hello, KeKe !
TNparam[0] : 4
TNparam[1] : 3
TNparam[2] : 2
TNparam[3] : 1
TNparam[4] : 5
TNparam[5] : 6
TNparam[6] : 7
TNparam[7] : 8
[Tekkaman2440@SBC2440V4]#


(15)“#include < linux/sched.h >”  最重要的头文件之一。包含驱动程序使用的大部分内核API的定义,包括睡眠函数以及各种变量声明。

(16)
#include < linux/version.h >” 包含所构造内核版本信息的头文件。

在学习过程中找到了几篇很好的参考文档:
(1)
第一章 模块(Modules) URL:http://greenlinux.blogcn.com/diary,103232026.shtml
(2)《
从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响》
URL:http://www.ibm.com/developerworks/cn/linux/l-module26/
(3)《Linux2.6内核驱动移植参考》
URL:http://blog.chinaunix.net/u1/40912/showart_377391.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值