




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
这是一个很简单的小例子hello world。也是Linux Device Drivers一书第二章的书读笔记。需要开发环境为了使得内核模块可以编译,我们需要安装kernel-devel的rpm包,例如在Fedora,我们需要yum install kernel-devel。如果使用的linux版本没有提供自动安装这个包,我们需要编译linux kernel来获得。这个包的相关文件放置在/usr/src/kernel/下面,他是kernel tree。小程序我们建立hello.c文件,下面是内容。黑体的部分是小程序主体部分,这部分已经足够作为一个完整的模块小程序,其他颜色是我们的一些试验。暗红色部分是处理携带参数加载模块的部分#include #include #include MODULE_LICENSE(Dual BSD/GPL);static char * whom = world;statci int howmany = 1;module_param(howmany,int,S_IRUGO);module_param(whom,charp,S_IRUGO);/* EXPORT_SYMBOL(xxxx);*/static int _init hello_init(void)int i = 0; printk(Hello world enter/n); for(i = 0 ; i howmany; i+) printk(Hello, %s/n, whom);/* 下面是KERN_ALERT的试验,这是一个macro,相当于字符串,注意请不要在后面加上逗号。*/ printk(KERN_ALERT Hello world module loaded!/n); /* 测试通过current(struct task_struct)获取当前进程名字和进程号,需要头文件linux/sched.h * KERN_INFO相当于字符串,即不显示任何内容,然而我们建议在程序中注明,以表示信息的*级别,使程序更为规范和可读 */printk(KERN_INFO The Process is %s, PID %i/n.current-comm,current-pid); return 0;static void _exit hello_exit(void) printk(Hello world exit!/n);module_init(hello_init);module_exit(hello_exit);头文件module.h中定义了很多用于加载模块的symbol和参数,init.h是用于初始化和cleanup函数,这两个头文件是模块编程中所必须的。另外moduleparam.h用于在模块加载的过程中传递参数,也是常用的头文件。module_init和module_exit用来kernel macros来表明模块加载时和卸载时的触发。这两个函数都是static,只用一次,因为不可能被其他文件所调用。 在module_init的类型为_init,这个表明这个函数只用于初始化,初始化完后,他的空间将被回收,可以用_initdata来表示只在初始化中使用数据,也将会被回收。一般的应用程序,在结束的时候,不需要仔细地去是否资源,因为进程终结,系统会自动进行。但是在kernel模块中,exit需要仔细地去删除所有init中建立或分配的资源,否则直到系统结束(例如reboot)这些资源才会释放,同样我们注意到这个类型为_exit,只用于unload。还有一个特别的宏定义MODULE_LICENSE来表明license,如果没有设定,那么在加载的时候,系统会提示:hello: module license unspecified taints kernel。可以是GPL v2,GPL and additional rigths等等, 如果不打算进行公开,可以使用Proprietary。如果需要其他的一些宏,例如MODULE_AUTHOR(), MODULE_VERSION(), MODULE_DESCRIPTION()等等,这些可以在linux/module.h中查看。kernel模块不允许链接函数,他只允许使用kernel定义的函数,include放置在/usr/src/kernel/$shell uname -r中。对于OS,kernel模块在kernel space中运行,而应用模块在user space运行。一个应用通过发出一个system call或者他由一个硬件中断所挂起是,可以从用户空间到内核空间。kernel module的错误可能会引起系统的崩溃,影响当前的进程,和普通程序不一样。在上面的小例子中,有一个被注释掉的EXPORT_SYMBOL(name),也可能是EXPORT_SYMBOL_GPL(name)。在内核模块中是没有链接啊或者库的说法,这并不是说明内核模块之间就是平面的结构,一个模块可以利用另一个模块的Symbol,这个在设备驱动中常见,例如很多设备都是基于USB的,那么他们可以使用usbcore,input模块中的symbol,如果我们的模块也希望可以被其他模块引用,需要使用上述的两种方式表明,而_GPL表示只能用于具有GPL版权的模块。这些Symbol都是全局的。内核模块可以携带参数调用,例如设备驱动可以携带一些与系统硬件有关的信息。参数说明为module_param(name, type, perm)以及数组module_param_array(name, type, num, perm)。type是类型,例如:bool, invbool, charp, int, long, short, uint, ulong, ushort。num实际是array的长度。perm是permission,相关的值可以在linux/stat.h中查到。S_IRUGO表示只读,可读可写表示为S_IRGO|S_IWUSR,0表示没有sysfs。在调用的时候,我们可以通过insmod hello.ko whom=Mom howmany=5来给出参数,我们可以不给出参数,采用缺省值,也可以只给出其中的一个参数。编译然后建立Makefile文件:#Makefile 2.6#表示模块是从hello.o建立的,名字为hello.koobj-m := hello.o#module-objs:如果模块由N个文件组成,那么其他文件就应该描述如下:module-objs:= file1.o file2.o,由于我们的模块叫做hello,在这个例子中应该写为hello-objshello-objs :=PWD := $(shell pwd)KDIR := /lib/modules/$(shell uname -r)/buildall:#-C表示kernel source目录,在/lib/modules/build,在那里可以找到kernel的最高lenvel的makefile,M=表示在建立模块target的时候,makefile回归到我们模块程序的目录。make -C $(KDIR) M=$(PWD) modulesclean : make -C $(KDIR) M=$(PWD) clean如果我们有多个c文件,可以在test-objs参数中加入他们的obj文件。接下来就是make了,编译后,生成hello.o文件和hello.ko,还有hello.mod.c及其obj文件,Module.markers Module.sysvers Modules.order 文件。我们对多个*.c文件情况做一个说明:我们希望创建一个模块的名字叫做hello,我们有三个*.c文件,分别为hello.c, file1.c和file2.c。这样是有问题的,因为在Makefile中obj-m := hello.o,这是指定模块的名称, hello-objs := file1.o file2.o hello.o,这里是说hello模块包括的的obj文件,如果我们在里面不填写hello.o,那么实际并没有编译hello.c,而是在CCM file1.o和file2.o,通过LDM得到模块hello.o,如果我们在这里填写了hello.o,那么在obj-m和hello-objs中都含有hello.o,对make来讲会产生循环和混淆,因此也不能这样书写。如果我们由多个C文件来构造一个模块,那么C文件的名字不能和模块名字一样,在这个例子中我们可以将hello.c改名为hello_main.c,在Makefile中obj-m := hello.o,hello-objs = file1.o file2.o hello_main.o。加载和卸载加载这个模块,可以使用insmod或者modprobe,运行lsmod,可以看到已经加载,通过rmmod命令来进行卸载,这些命令需要具备root的权限。 和imsnod相比,modprobe会查看被下载的模块里面的symbols有没有在kernel中没有定义的,如果发现有没定义的, 他将在该模块的路径下找寻其他模块是否含有这些定义,如果含有将他们也一并load。对于这种情况insmod或者modprobe没有找到匹配的模块,将会报告:unresolved symbols。使用lsmod当前加载的模块,实际相当于cat /proc/modules。如果想查看printk的结果,系统输出在console,如果我们使用init 3进入我们的系统, 即使用命令行方式,那么我们可以直接看到输出的结果,如果我们是在图形界面中的terminal或者console,又或者是通过远程访问的方式,这个输出是看不到的,可以使用dmesg命令来查看。也可以在/var/log/messages中查看。一般调测,我喜欢使用dmesg。和Kernel版本匹配的问题我们需要注意的内核模块和kernel是密切相关的,如果我们试图加载一个模块但是不能和kernel兼容,则报告类似下面的错误:Error inserting ./hello.ko: -1 Invalid module format。这是有kernel中vermagic.o来判定的。由于每个版本kernel的改动都会影响我们,如果我们需要一个模块同时能在多个版本中工作,维护源代码的一致性,需要加上#ifdef之类的定义,可以使用linux/utsrelease.h下面的UTS_RELESE,liux/version.h下面的LINUX_VERSION_CODE或者KERNEL_VERSION。后两者将他们值转换为0x的16进制格式 ,比较清晰。我们说的只是源代码的一致性,仍需要指定不同的KDIR来进行编译。对于这种情况,根据我们的编程思想,我们将low-level的代码,需要通过宏来指定的部分,和high-level的代码,相对和OS版本独立,或者能够通过底层代码屏蔽差异的部分分开,这样程序变得易读,容易维护。如果作为一个商业版本进行发布,如果需要面临不同的OS版本,或者OS以后升级的不同的版本,最好的方式能过进入upstream的official linux kernel,否则作为 GPL,公布source,允许在不同的版本中用户自行编译,我们也可以将这些步骤制作成小工具发布。如果提供的是binary的方式,应当指明kernel的版本,应考虑到以后OS升级的问题。在初始化过程中出现错误的处理由于某些原因,在初始化的过程会出现一些错误。如果出现在register的过程,我们可以选择让初始化继续进行,降低模块提供的功能,这是通常的做法如果我们认为错误严重无法加载模块,为了释放kernel空间,我们应该清除所有在错误之前的注册。 在通常的程序中,goto是不受欢迎的,但是它并没有在C中删除,而在模块编程中,使用goto来处理错误反而会减少复杂度,增加可读性,因此在内核中,goto常用于处理错误。下面是一个例子:struct st1 * item1;struct st2 * item2;int stuff_ok;/* 我们注意到这里没有使用_exit,因为这个函数不会只在unload的时候调用,这点需要注意。*/void my_cleanup(void) if(item) release_func(item1); if(item2) release_func2(item2); if(stuff_ok) unregister_stuff(); return;int _init my_init(void) int err = -ENOMEN; item1 = allocate_func(arg); item2 = allocate_func2(arg2); if(!item1 | !item2)goto fail; err = register_stuff(item1, item2); if( ! err) stuff_ok =1; else goto fai
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 项目进度汇报与问题解决方案表
- (正式版)DB15∕T 3262-2023 《混播人工草地放牧利用技术规范》
- (正式版)DB15∕T 3241-2023 《草原瑞香狼毒发生等级划分技术规程》
- (正式版)DB15∕T 3213-2023 《黄河流域西瓜、甜瓜主要病虫害绿色防控与蜜蜂授粉融合技术规程》
- 护理学三基简答题题库及答案
- 医院外科护理考试题库及答案
- 企业财务报告制作标准化指南
- 儿科护理学期末押题题库及答案
- 行业标准化操作指南汇编
- 农业科技园农业技术支持与培训协议
- 西畴殡葬管理办法
- 小学生意外伤害课件
- 银行外包人员管理办法
- 2024年法考主观题刑法真题(回忆版)解析与复习重点
- 数字媒体技术专业教学标准(高等职业教育专科)2025修订
- 妊娠合并心脏病疾病查房
- 消防安全评价管理制度
- 2025至2030年中国二手车金融行业市场行情监测及发展前景研判报告
- 2023年5月7日全国事业单位联考A类《职业能力倾向测验》试题真题答案解析
- 正念心理治疗
- 2025成人高考民法真题及答案
评论
0/150
提交评论