




已阅读5页,还剩1页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
编写简单的Linux2.6内核模块(1) 本文我们将编写并引导一个简单的内核模块。编写自己的模块让您能够编写一些独立的内核代码,学习如何使用模块,并发现内核如何连接到一起的一些规则。 注意:这些说明是为 2.6.x 内核缩写的,可能不适用于另外的内核版本。 您的内核必须已经启用这些选项进行了编译:Loadable module support - * Enable loadable module support * Module unloading Module versioning support (EXPERIMENTAL) * Automatic kernel module loading如果按照第一篇教程中的说明编译内核,那么就已经正确地设置了这些选项。否则,修改这些选项,重新编译内核,并引导到新内核。一个简单的模块骨架首先,找到编译当前 Linux 内核的源代码。将目录切换到 Linux 源代码目录中的 drivers/misc/。现在,拷贝下面的代码并将其粘贴到一个名为 mymodule.c 的文件:#include #include #include static int _init mymodule_init(void) printk (My module worked!n); return 0;static void _exit mymodule_exit(void) printk (Unloading my module.n); return;module_init(mymodule_init);module_exit(mymodule_exit);MODULE_LICENSE(GPL);保存这个文件,并在同一目录下编辑 Makefile 文件。添加这一行: obj-m += mymodule.o编译模块: # make -C SUBDIRS=$PWD modules使用 insmod ./mymodule.ko 加载这个模块,并查看是否打印了您的消息: dmesg | tail。应该会在输出的结束处看到: My module worked!现在删除内核模块:rmmod mymodule。再次查看 dmesg;应该会看到: Unloading my module.这样您就已经编写并运行了一个新的内核模块!恭喜! 模块/内核接口现在,我们来做一些与您的模块有关的更有趣的事情。要了解的一个关键内容是,模块只能“看到”内核故意让它访问的函数和变量。首先,我们以错误的方式来进行尝试。编辑文件 kernel/printk.c,在所有包含文件之后其他全局变量声明附近(但要在所有函数之外)添加下面一行:int my_variable = 0;现在重新编译内核并引导到新内核。然后,将下面的内容添加到模块的 mymodule_init 函数起始处,置于其他代码之前。 extern int my_variable;printk (my_variable is %dn, my_variable);my_variable+;保存修改并重新编译模块: # make -C SUBDIRS=$PWD modules加载模块(这将失败):insmod ./mymodule.ko。模块的加载会失败,并给出消息: insmod: error inserting ./mymodule.ko: -1 Unknown symbol in module这说明内核不允许模块访问那个变量。当模块加载时,它必须解析所有外部引用,比如函数名或者变量名。如果它不能找到内核导出的符号列表中所有未解析的名称,那么模块就不能写入那个变量或者调用那个函数。在内核中某个地方有为变量 my_variable 分配的空间,但模块不知道是哪里。 为解决此问题,我们将把 my_variable 添加到内核导出的符号列表中。在很多内核目录中,都有一个特定的文件,用于导出在那个目录中定义的符号。再次打开 kernel/printk.c 文件,在变量声明之后添加下面一行:EXPORT_SYMBOL(my_variable);重新编译并重新引导到新内核。现在再一次尝试加载模块:insmod ./mymodule.ko。这一次,当查看 dmesg 时,应该看到: my_variable is 0My module worked!重新加载模块: # rmmod mymodule & insmod ./mymodule.ko现在应该看到: Unloading my module.my_variable is 1My module worked!每次重新加载那个模块,my_variable 都会增 1。您正在读写一个在主内核中定义的变量。只要被 EXPORT_SYMBOL() 显式地声明,模块就可以访问主内核中的任何变量。例如,函数 printk() 是在内核中定义的,并且在文件 kernel/printk.c 中被导出。 简单的可引导内核模块是用来研究内核的一个有趣的途径。例如,可以使用一个模块来打开或关闭 printk,方法是在内核中定义一个变量 do_print(它初始化为 0)。然后,让所有 printk 都依赖于“do_print”:if (do_print) printk (Big long obnoxious messagen);然后,只有当您的模块被加载时才打开它。 模块参数引导模块时,可以向它传递参数。要使用模块参数加载模块,这样写:insmod module.ko param1=value param2=value .为了使用这些参数的值,要在模块中声明变量来保存它们,并在所有函数之外的某个地方使用宏 MODULE_PARM(variable, type) 和 MODULE_PARM_DESC(variable, description) 来接收它们。type 参数应该是一个格式为 min-maxb,h,i,l,s 字符串,其中 min 和 max 是数组的长度限度。如果两者都忽略了,则默认为 1。最后一个字符是类型说明符: b byteh shorti intl longs string可以在 MODULE_PARM_DESC 的 description 域中添加任何需要的说明符。 EXPORT_SYMBOL的问题 一个模块mod1中定义一个函数func1;在另外一个模块mod2中定义一个函数func2,func2调用func1。在模块mod1中,EXPORT_SYMBOL(func1);在模块mod2中,extern int func1();就可以在mod2中调用func1了。参考:/u/20070910/09/ee2cff13-9179-41e3-9292-4fd73261f709.html/msdn-archive/524/kernel-driver-5244619.shtmmod1.c#include#include#includestatic int func1(void) printk(In Func: %s.n,_func_); return 0;EXPORT_SYMBOL(func1);static int _init hello_init(void) printk(Module 1,Init!n); return 0;static void _exit hello_exit(void) printk(Module 1,Exit!n);module_init(hello_init);module_exit(hello_exit);#mod2.c#include#include#includestatic int func2(void) extern int func1(void); func1(); printk(In Func: %s.n,_func_); return 0;static int _init hello_init(void) printk(Module 2,Init!n); func2(); return 0;static void _exit hello_exit(void) printk(Module 2,Exit!n);module_init(hello_init);module_exit(hello_exit);#Makefileifneq ($(KERNELRELEASE),)obj-m := XXXX.oelseKDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modulesclean: rm -rf Module.symvers *.ko *.o *.mod.c .*.cmd .tmp_versionsendif#insmod ./mod1.ko#insmod ./mod2.ko#rmmod mod2#rmmod mod1Jan 11 11:59:17 wangyao-desktop kernel: 9886.801010 Module 2,Exit!Jan 11 11:59:21 wangyao-desktop kernel: 9891.450214 Module 1,Exit!Jan 11 12:05:29 wangyao-desktop kernel: 10258.385014 Module 1,Init!Jan 11 12:05:38 wangyao-desktop kernel: 10267.465923 Module 2,Init!Jan 11 12:05:38 wangyao-desktop kernel: 10267.465928 In Func: func1.Jan 11 12:05:38 wangyao-desktop kernel: 10267.465930 In Func: func2.Jan 11 12:05:50 wangyao-desktop kernel: 10280.091755 Module 2,Exit!Jan 11 12:05:57 wangyao-desktop kernel: 10287.332596 Module 1,Exit!可见,在mod2中的func2函数成功的调用了mod1中的func1函数。注意:在编译mod2的时候,出现一个WARNING:rootwangyao-desktop:/modules/export_symbol/mod2# makemake -C /lib/modules/2.6.22-14-generic/build SUBDIRS=/root/modules/export_symbol/mod2 modulesmake1: Entering directory /usr/src/linux-headers-2.6.22-14-generic Building modules, stage 2. MODPOST 1 modul
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 国家事业单位招聘2025中国农业科学院农产品加工研究所统招博士研究生(西南大学联培项目)拟笔试历年参考题库附带答案详解
- 北京市2025北京三门峡黄河明珠(集团)有限公司招聘高校毕业生8人笔试历年参考题库附带答案详解
- 2025河北邢台经济开发区国企叶片厂招聘100人笔试参考题库附带答案详解
- 2025春季福建宁德港务集团校园招聘12人笔试参考题库附带答案详解
- 2025年湖南省高速公路集团有限公司春季校园招聘167人笔试参考题库附带答案详解
- 2025年望城经开区招商投资有限公招聘9人笔试参考题库附带答案详解
- 2025年宿迁市宿城区创新投资集团有限公司公开招聘5人笔试参考题库附带答案详解
- 2025年合肥工科同道产业园管理有限公司招聘15人笔试参考题库附带答案详解
- 2025山东济南福和数控机床有限公司招聘30人笔试参考题库附带答案详解
- 2025四川长虹置业有限公司招聘置业顾问(现场售楼员)岗位4人笔试参考题库附带答案详解
- 管理者角色认知与转换课件
- 五牌一图(完整版)
- 教科版科学二年级上册 全册整套课件
- 六年级上册数学教案-第一单元复习教案|人教新课标版
- 小学道德与法治学科教师专业素质考试试题及答案
- GB∕T 23322-2018 纺织品 表面活性剂的测定 烷基酚和烷基酚聚氧乙烯醚
- 全国质量奖现场汇报材料(生产过程及结果)课件
- 政策评价-卫生政策分析课件
- 高中物理实验—测定物体的速度及加速度(含逐差法)
- 饮食习惯与健康
- 华为人力资源管理纲要2.0
评论
0/150
提交评论