分类: LINUX
2013-09-24 16:00:16
前段时间对内核态和用户态交互的两种方式:netlink套接字和procfs进行了皮毛层次的了解,感觉这个东西还挺有意思的,于是打算深入的学习下linux内核态和用户态交互的各种方法。
内核态和用户态有不同的地址空间,因此,在内核和应用之间以及在应用与应用之间进行数据交换需要专门的机制来实现,内核态与用户态数据交换的方式包括内核启动参数、模块参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs 和 relayfs。近段时间讲着重对procfs,netlink,和系统调用进行学习研究,后续再对其他方式进行学习。
好了,长话短说,先从最基本的来吧。
charpter 1 :学会给内核添加一个模块
这里是我写的一个示例模块:
1.两个头文件:linux/module.h linux/init.h是模块编写所必须的。
2.其中两个宏函数:module_init(),module_exit()。module_init在模块加载的时候会被调用,也就是如果此模块被编译成外部模块,则在执行insmod *.ko时候调用module_init,在执行rmmod *.ko时候调用module_exit.(貌似将模块编译进内核里面的话,module_init和module_exit没必要必须定义,还不太确定过后尝试下)
3.关于MODULE_LICENSE():可以为MODULE_LICENSE(Proprietary);或者为MODULE_LICENSE("GPL");使用前者会出现的结果是你不能调用系统提供的以EXPORT_SYMBOL_GPL 导出的函数。
如何去编译这个模块,这里会出现两种情况:
1.编译成可动态加载的模块:
添加Makefile:
make -C /usr/src/linux-2.6.15.5/ M=$(PWD) modules
-C后面是内核源代码的目录 M=后面是要编译的模块的目录(这里是当前路径)。这种编译方法仅在2.6以上的内核版本上行的通。因为这里牵扯到Kbuild的语法,linux内核2.6开始针对linux内核采用Kbuild编译系统,关于Kbuild我在这里也不多说了,看了一些资料,有些地方还是有些糊涂,等过段时间研究透彻了再放出学习心得。在这里我只是对这个makefile做一些简单的介绍:KERNELRELEASE是内核源码顶层的makefile中定义的一个变量,在第一次读取执行此makefile时此变量没有被定义,所以make将执行else之后的内容,如果make的目标是clean则直接执行,如果make的目标是all,-C$(K_DIR)指明跳转到内核源码目录下读取并执行那里的makefile,M=$(M_DIR)表明然后返回到当前目录下继续读入执行当前的makefile,当从内核源码返回时KERNELRELEASE已经被定义,Kbuild也会被启动去解析Kbuild语法的语句,make将继续执行else前的语句,else之前的语句为Kbuild语法的语句指明了模块的依赖关系,以及要生成的目标模块的名称。
2.编译到内核里:
只需要将obj -m改成obj-y