HelloWorld内核
开始断断续续学习内核,大概半年了,多少开始对内核有点感悟了,但是对于这个庞然大物我显得很渺小,在枯燥的内核源码之中似乎没有一点点成功的喜悦,因此我选择学习内核模块编程,通过编写一些内核模块来体验那一点点小小的成就感吧!
什么是内核模块
内核模块是具有独立功能的程序。它可以被单独编译,但是不能单独运行,它的运行必须被链接到内核作为内核的一部分在内核空间中运行。
最简单的内核模块
#include
一个Makefile来编译这个内核模块
obj-m += hello-1.oall: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
注意:本文所有环节都是基于Centos6.5下测试OK,你可能在有的书上看见Makefile是这样写的
make -C /usr/src/linux-headers-$(shell uname -r) M=$(PWD) modules 其实/lib/modules/$(shell uname -r)/build 这个路径就是上面路径的一个软链接 [root@localhost 2.6.32-431.el6.x86_64]# ls -al build lrwxrwxrwx. 1 root root 44 Mar 16 05:26 build -> /usr/src/kernels/2.6.32-504.12.2.el6.x86_64/
编写好makefile文件后,使用make进行编译,编译完就出现一个.ko的文件,这个就是内核模块,需要载入运行
载入内核模块进行运行
载入内核模块的方法有很多比如: modprobe 和 insmod前者会分析模块的依赖关系,并且会去指定路径查找内核模块载入,而后者需要指定内核模块的绝对路径进行载入并且不解决模块的依赖关系。这里我们使用insmod来载入内核模块,使用rmmod卸载内核模块 [root@localhost kernel_module]# insmod hello-1.ko使用dmes查看内核模块的输出Hello world 1.卸载内核模块 [root@localhost kernel_module]# rmmod hello-1 dmesg查看输出Goodbye world 1.
内核模块编程和应用程序编程的异同
内核模块编程是不能去使用标准库(比如malloc free等)和一些第三方的库
内核模块编程是没有内存保护的,如果内存访问错误,就会出现oops错误
内核模块编程是没有main函数的,只有一个初始化函数,和一个提出函数
内核模块编程需要使用内核提供的头文件和API
内核模块编程的标准输出是输出到文件,而不是输出到屏幕
内核模块编程的debug是不能使用gdb来进行调试的。
内核模块进阶
内核模块的编程不仅仅是上面的一个HelloWorld,内核模块编程还有一些更高级的写法,下面会一一介绍:
去掉init_module/cleanup_module
在上面的HelloWorld模块中,你会发现初始化函数和退出函数好像是固定的名称,那么有没有办法自己自定义名称呢其实是可以的,你可以自己自定义名称,然后进行注册即可(注册其实就是做了一个函数指针的赋值而已)下面是自定义名称的写法:
//不需要固定内核模块的初始化函数的名字和结束的名字#include
__init/__initdata/__exit
在有的内核模块编程的书籍或者介绍内核模块编程的博客中,你或许会发现有这样的一些特殊关键字__init ,_initdata ,__exit等等,其实这些都是gcc的扩展属性:__init宏最常用的地方是驱动模块初始化函数的定义处,其目的是将驱动模块的初始化函数放入名叫.init.text的输入段。当内核启动完毕后,这个段中的内存会被释放掉供其他使用。__initdata宏用于数据定义,目的是将数据放入名叫.init.data的输入段。其它几个宏也类似。
模块描述信息
可以使用modinfo去查看一个模块的模块信息,下面是自己编写的模块和系统自带的模块的两个模块信息的对比
[root@localhost kernel_module]# modinfo hello-1.kofilename: hello-1.kosrcversion: 0D3956C127A907CC9E7114Fdepends: vermagic: 2.6.32-504.12.2.el6.x86_64 SMP mod_unload modversions [root@localhost kernel_module]# modinfo/lib/modules/2.6.32-431.el6.x86_64/kernel/fs/ext4/ext4.ko filename: /lib/modules/2.6.32-431.el6.x86_64/kernel/fs/ext4/ext4.kolicense: GPLdescription: Fourth Extended Filesystemauthor: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others srcversion: 345EBDA2AEFF60FFED78864 depends: mbcache,jbd2 vermagic: 2.6.32-431.el6.x86_64 SMP mod_unload modversions
从上面的对比可知,自己编写的模块的模块信息很少,没有作者信息,没有许可证信息等等,其实这些都可以设置
#include
模块参数
在用户态编写程序的时候我们都应该清楚,是可以给程序传递参数的,那么同样内核模块同样也有这样的需求,下面的例子展示了如何去给内核模块传递参数:
#include
模块文件分割
在用户态写程序的时候,你会将一个大的程序分割成好几个文件,这样程序脉络就显的很清晰。在这里我们将初始化函数和退出函数分开在两个文件中编写。
start.c中#include
-
helloworld
+关注
关注
0文章
13浏览量
4358 -
内核模块
+关注
关注
0文章
10浏览量
3081
原文标题:黑客内核:编写属于你的Hello world
文章出处:【微信号:C_Expert,微信公众号:C语言专家集中营】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论