linux驱动的入口函数module_init的加载和释放

linux驱动的入口函数module_init的加载和释放

ID:11071507

大小:57.50 KB

页数:5页

时间:2018-07-09

linux驱动的入口函数module_init的加载和释放_第1页
linux驱动的入口函数module_init的加载和释放_第2页
linux驱动的入口函数module_init的加载和释放_第3页
linux驱动的入口函数module_init的加载和释放_第4页
linux驱动的入口函数module_init的加载和释放_第5页
资源描述:

《linux驱动的入口函数module_init的加载和释放》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、就像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:#include#include#include其中,init.h定义了驱动的初始化和退出相关的函数,kernel.h定义了经常用到的函数原型及宏定义,module.h定义了内核模块相关的函数、变量及宏。几乎每个linux驱动都有个module_init(与module_exit的定

2、义在Init.h(/include/linux)中)。没错,驱动的加载就靠它。为什么需要这样一个宏?原因是按照一般的编程想法,各部分的初始化函数会在一个固定的函数里调用比如:voidinit(void){init_a();init_b();}如果再加入一个初始化函数呢,那么在init_b()后面再加一行:init_c();这样确实能完成我们的功能,但这样有一定的问题,就是不能独立的添加初始化函数,每次添加一个新的函数都要修改init函数。可以采用另一种方式来处理这个问题,只要用一个宏来修饰一下:voidin

3、it_a(void){}__initlist(init_a,1);它是怎么样通过这个宏来实现初始化函数列表的呢?先来看__initlist的定义:[cpp]viewplaincopy1#define__init__attribute__((unused,__section__(".initlist")))23#define__initlist(fn,lvl)/4staticinitlist_t__init_##fn__init={/5magic:INIT_MAGIC,/6callback:fn,/7leve

4、l:lvl}请注意:__section__(".initlist"),这个属性起什么作用呢?它告诉连接器这个变量存放在.initlist区段,如果所有的初始化函数都是用这个宏,那么每个函数会有对应的一个initlist_t结构体变量存放在.initlist区段,也就是说我们可以在.initlist区段找到所有初始化函数的指针。怎么找到.initlist区段的地址呢?externu32__initlist_start;externu32__initlist_end;这两个变量起作用了,__initlist_s

5、tart是.initlist区段的开始,__initlist_end是结束,通过这两个变量我们就可以访问到所有的初始化函数了。这两个变量在那定义的呢?在一个连接器脚本文件里[cpp]viewplaincopy1.=ALIGN(4);2.initlist:{3__initlist_start=.;4*(.initlist)5__initlist_end=.;6}这两个变量的值正好定义在.initlist区段的开始和结束地址,所以我们能通过这两个变量访问到所有的初始化函数。与此类似,内核中也是用到这种方法,所以

6、我们写驱动的时候比较独立,不用我们自己添加代码在一个固定的地方来调用我们自己的初始化函数和退出函数,连接器已经为我们做好了。先来分析一下module_init。定义如下:[cpp]viewplaincopy7#definemodule_init(x)__initcall(x);//include/linux/init.h89#define__initcall(fn)device_initcall(fn)1011#definedevice_initcall(fn)__define_initcall("6",f

7、n,6)1213#define__define_initcall(level,fn,id)/1415staticinitcall_t__initcall_##fn##id__used/1617__attribute__((__section__(".initcall"level".init")))=fn如果某驱动想以func作为该驱动的入口,则可以如下声明:module_init(func);被上面的宏处理过后,变成__initcall_func6__used加入到内核映像的".initcall"区。内核的

8、加载的时候,会搜索".initcall"中的所有条目,并按优先级加载它们,普通驱动程序的优先级是6。其它模块优先级列出如下:值越小,越先加载。[cpp]viewplaincopy1#definepure_initcall(fn)__define_initcall("0",fn,0)23#definecore_initcall(fn)__define_initcall("1",fn,1)45#definecore_

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。