模块的作用及模块Makefile的解析

在学习编写Linux内核模块的时候我们首先要清楚的知道内核模块的作用,为什么要使用内核模块?这是因为Linux内核的整体结构非常的庞大,包含的组件也非常的多,把所有的内核模块都编译到Linux内核,会导致的问题是内核很大,同时在现有的内核新增或删除部分功能时,不得不重新编译内核,可谓相当的费时。而模块的使用就是为了解决这一问题,即动态的在内核中添加或者删除相应功能。下面以一个经典的代码来看是相关的分析:
 
#include
#include

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("xxx");
MODULE_DESCRIPTION("Hello World Module");
MODULE_ALIAS("a simplest module");
 
static int __init hello_init()
{
    printk(KERN_EMERG"Hello World!\n");  //注意比较两种printk( )参数的不同之处
    return 0;                                                     //即优先级的用法
}
 
static void __exit hello_exit()
{
    printk("<6>hello exit\n");
}
 
module_init(hello_init);
module_exit(hello_exit);
在阅读相关的代码时我们的入口点不再是main( )函数,而应该是module_init( 函数名 )函数;细心的话就会发现在hello_init()函数前面有一个__init ,它的作用是在连接的时候把标识的函数放在 .init.text这个区段内。此外所有的__init函数在区段 .initcall.init中还保存了一个函数指针,在初始化的时候内核会通过这些函数指针调用这些__init 函数,在完成初始化后释放掉该区段。
 
printk( )函数和平printf( )函数类似,但是printk( )函数有打印优先级(数值越低,优先级越高),如果这个打印优先级比默认的低,那么将看不到输出,所以在使加载和卸载模块的过程中如果看不到打印语句,这是一个值得分析的问题。查看默认优先级的语句为:cat    /proc/sys/kenel/printk
 
在代码的起始部分我们给出了如下代码:
 
1.  MODULE_LICENSE("Dual BSD/GPL");
2.  MODULE_AUTHOR("xxx");
3.  MODULE_DESCRIPTION("Hello World Module");
4.  MODULE_ALIAS("a simplest module");
 
1.为必须选择的语句,它是模块的许可权限,如果不声明,会出现警告信息。
 
2.3.4为可选项,其为模块的一些相关信息。如作者、实现的功能等。
 
最后自然到了module_exit(hello_exit),有加载必须要有卸载,呵呵……做事要有始有终嘛,所以这自然就是相关的卸载部分了。其中的printk( )和前面的分析完全一样。
 
外加一点,如果模块有参数的传递,那么还需使用module_param(参数名,参数类型,参数的读/写权限),当参数为数组时,使用module_param_array(数组名,数组类型,数组长,参数读/写权限)。
 
懂了模块的编写,接下来就应该是模块的编译了,在当前路径下建立一个Makefile文件,编写如下代码:
 
ifneq ($(KERNELRELEASE),)
 
obj-m := hello.o           //hello为你编写的模块代码保存名(在此保存的为hello.c) ,编译生成目标文件hello.o(注意:隐式规则)
 
else
 
KDIR := /lib/modules/2.6.18-53.el5/build    //KDIR是本Makefile 依赖的linux内核源码路径  ,如是交叉编译时就取开发板上运行的源码路径
all:
 make -C $(KDIR) M=$`PWD` modules
 
 //到linux源码所在的目录执行主Makefile 并当前路径传给主Makefile,告诉主Makefile执行完后返回到当前目录,执行Makefile,
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers
 
endif
 
KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时, KERNELRELEASE没有被定义,所以make将读取执行else之后的内容。如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句, 指明模块源码中各文件的依赖关系,以及要生成的目标模块名。
 
该Makefile(注意Makefile中的M要大写,具体原因自己可查资料,在次就不一一讲解了)的编写一般都具有固定的格式,变化很少,可以当成模板来记。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值