linux 驱动开发-模块的构建
1.模块的含义 linux 是採用模块化的方式构建的,同意内核在执行时动态地向当中插入或从中删除代码。这些代码(包扩函数,数据,模块入口函数,模块出口函数)被一并组合 在一个单独的二进制镜像,就是所谓的可装载内核模块。 模块能够是主要的内核镜像尽可能小,同一时候能够方便地对新功能进行调试。还能够实现热插拔(兴许会学习怎样实现设备的热插拔功能,临时无需深究),和内核的核心子系统不一样,模块文件须要有入口点和出口点。 模块与应用程序的差别: a.模块和库函数相似,一个模块通常包括若干函数和数据,每一个函数提供特定的服务。决定完毕哪些功能则是应用程序的事情,模块仅仅是用来为应用程序提供服务。也就是策略与机制的关系。模块提供机制,应用程序依据模块提供的机制实现策略。 b.模块的注冊函数仅仅是把模块注冊到内核中。模块中的函数怎样被调用是应用程序的事情。 c.应用程序退出是能够无论资源的释放和其它清理工作(通常我们还是会处理),但模块的退出函数必须细致撤销初始化函数所作的一切。 d.模块被链接到内核,它仅仅能调用哪些被内核导出的函数(以后会讲到怎样导出内核函数),使用的头文件是内核源码中include/文件夹下的头文件,如: #include<linux/init.h>?? ======>include/linux/init.h e.模块不会和不论什么库链接 f.模块编程必须谨慎考虑并发问题,通常必须是可重入的。 2.模块的编译,装载和卸载。 请參考linux内核稳定。有很具体的描写叙述。 Documentation/kbuild/modules.txt 由于文档是英文。我简单描写叙述一下。 a.首先执行makefile编译模块,简单分析make的编译參数 make -C? 将文件夹改变到内核源码所在文件夹,当中有内核的顶层makefile文件。 M=‘pwd’? 要求顶层makefile在构造modules目标之前返回到模块的源码文件夹。 modules 仅仅想obj-m变量中设定的模块。就是告诉编译系统,此make 是要编译一个内核模块。 内核转载和卸载的命令 insmod insmod和ld相似。但insmod不
假设内核觉得模块仍然处于使用状态,有可能无法卸载。在编译内核时须要将Loadable module s??? upport-->Module unloading选中,否则内核不支持模块卸载。
lsmod程序列出了当前装载到内核中的所以模块,还列出了其它信息,如其它模块是否在使用某个特点模块。lsmod通过读取/proc/modules获得这些信息。 上面的基本知识大家有个大概的印象就可以,以下演示样例分析一下,一些程序学习的起源都是Hello world, 那么我们也从Hello world開始。创建一个简单的Hello world 模块。 首先构建模块编译的makefile文件 #Makefile obj-m = hello.o KERN = /share/arm/linux-3.2 #基于源码树的模块编译。源码树必须要先编译完毕后,才干进行模块编译 # KERN = /lib/modules/`uname -r`/build/ ##假设你在x86平台的linux系统,直接能够编译基于x86平台的模块 all: make -C $(KERN) M=`pwd` modules clean: make -C $(KERN) M=`pwd` modules clean rm -rf modules.order看看首个模块代码helloWorld.c #include <linux/init.h> #include <linux/module.h> //模块必须的两个头文件 MODULE_LICENSE("GPL"); //GPL协议要求 MODULE_AUTHOR("MJ"); //option 描写叙述作者信息 MODULE_DESCRIPTION("just for test"); //option 描写叙述模块的 static __init int hello_init(void) { printk(KERN_EMERG,"hello kernel !n"); //printk 相似应用程序的printf。 使用方法稍有不同,可百度一下。} static __exit void hello_exit(void) { printk(KERN_EMERG,"bye,cruel world!n"); } module_init(hello_init); module_exit(hello_exit);通常printk不能直接输出到终端,须要看终端的配置及你printk的打印机别。 可是一定会输出到log文件,你能够用dmesg 命令查看log message。
printk() 如: 缺省级别在printk.c中指定。 能够通过dmesg查看。
printk()能够在中断中调用。 (7)模块的初始化和清除
本文对linux 模块进行主要的介绍。让大家对linux模块有个主要的认识。 下一篇文章将对模块的其它特性进行解说 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |