ImageVerifierCode 换一换
格式:DOCX , 页数:7 ,大小:16.91KB ,
资源ID:28726883      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/28726883.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(系统初始化函数集subsysinitcall和初始化段应用.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

系统初始化函数集subsysinitcall和初始化段应用.docx

1、系统初始化函数集subsysinitcall和初始化段应用系统初始化函数集(subsys_initcall)和初始化段应用系统初始化函数集(subsys_initcall)和初始化段应用前言:前段时间做一个项目需要设计一个动态库,并希望在加载库的同时自动执行一些初始化动作,于是联想到了linux内核众子系统的初始化,于是研究之,并在过这程中发现了初始化段的存在,利用初始化段实现了该功能。工作一年,笔记积累多了,慢慢变得杂乱无章,于是开博,一方面整理笔记,梳理知识,另一方面和大家交流,共同进步。keyword:subsys_initcall, init, init_call1 系统初始化调用函数

2、集分析(静态)1.1 函数定义 在linux内核代码里,运用了subsys_initcall来进行各种子系统的初始化,具体怎么初始化的呢?其实并不复杂。以2.6.29内核作为例子。在下就能找到subsys_initcall的定义:#define pure_initcall(fn) _define_initcall(0,fn,0)#define core_initcall(fn) _define_initcall(1,fn,1)#define core_initcall_sync(fn) _define_initcall(1s,fn,1s)#define postcore_initcall(fn

3、) _define_initcall(2,fn,2)#define postcore_initcall_sync(fn) _define_initcall(2s,fn,2s)#define arch_initcall(fn) _define_initcall(3,fn,3)#define arch_initcall_sync(fn) _define_initcall(3s,fn,3s)#define subsys_initcall(fn) _define_initcall(4,fn,4)#define subsys_initcall_sync(fn) _define_initcall(4s,f

4、n,4s)#define fs_initcall(fn) _define_initcall(5,fn,5)#define fs_initcall_sync(fn) _define_initcall(5s,fn,5s)#define rootfs_initcall(fn) _define_initcall(rootfs,fn,rootfs)#define device_initcall(fn) _define_initcall(6,fn,6)#define device_initcall_sync(fn) _define_initcall(6s,fn,6s)#define late_initca

5、ll(fn) _define_initcall(7,fn,7)#define late_initcall_sync(fn) _define_initcall(7s,fn,7s)而_define_initcall又被定义为#define _define_initcall(level,fn,id) static initcall_t _initcall_#fn#id _used _attribute_(_section_(.initcall level .init) = fn所以 subsys_initcall(fn) = _initcall_fn4 它将被链接器放于section .initca

6、ll4.init 中。(attribute将会在另一篇文章中介绍)1.2 初始化函数集的调用过程执行过程:start_kernel-rest_init系统在启动后在rest_init中会创建init内核线程init-do_basic_setup-do_initcallsdo_initcalls中会把.initcall.init.中的函数依次执行一遍:for (call = _initcall_start; call _initcall_end; call+) . .result = (*call)();. .这个_initcall_start是在文件定义的: .initcall.init :

7、AT(ADDR(.initcall.init) - LOAD_OFFSET) _initcall_start = .; INITCALLS _initcall_end = .; INITCALLS被定义于:#define INITCALLS *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.i

8、nitcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)2 基于模块方式的初始化函数(动态)2.1函数定义subsys_initcall的静态调用方式应该讲清楚来龙去脉了,现在看看动态方式的初始化函数调用(模块方式)。在里,如果MODULE宏被定义,说明该函数将被编译进模块里,在系统启动后以模块方式被调用。#define core_initc

9、all(fn) module_init(fn)#define postcore_initcall(fn) module_init(fn)#define arch_initcall(fn) module_init(fn)#define subsys_initcall(fn) module_init(fn)#define fs_initcall(fn) module_init(fn)#define device_initcall(fn) module_init(fn)#define late_initcall(fn) module_init(fn)这是在定义MODULE的情况下对subsys_in

10、itcall的定义,就是说对于驱动模块,使用subsys_initcall等价于使用module_init2.2 module_init 分析下面先看看module_init宏究竟做了什么#define module_init(initfn) static inline initcall_t _inittest(void) /*定义此函数用来检测传入函数的类型,并在编译时提供警告信息*/ return initfn; int init_module(void) _attribute_(alias(#initfn); /*声明init_modlue为 initfn的别名,insmod只查找名字为

11、init_module函数并调用*/typedef int (*initcall_t)(void); /*函数类型定义*/在以模块方式编译一个模块的时候,会自动生成一个xxx.mod.c文件, 在该文件里面定义一个struct module变量,并把init函数设置为上面的init_module() 而上面的这个init_module,被alias成模块的初始化函数(参考)。 也就是说,模块装载的时候(insmod,modprobe),sys_init_module()系统调用会调用module_init指定的函数(对于编译成模块的情况)。2.3 module的自动加载内核在启动时已经检测到了

12、系统的硬件设备,并把硬件设备信息通过sysfs内核虚拟文件系统导出。sysfs文件系统由系统初始化脚本挂载到/sys上。udev扫描sysfs文件系统,根据硬件设备信息生成热插拔(hotplug)事件,udev再读取这些事件,生成对应的硬件设备文件。由于没有实际的硬件插拔动作,所以这一过程被称为coldplug。udev完成coldplug操作,需要下面三个程序: udevtrigger扫描sysfs文件系统,生成相应的硬件设备hotplug事件。 udevd作为deamon,记录hotplug事件,然后排队后再发送给udev,避免事件冲突(race conditions)。 udevsett

13、le查看udev事件队列,等队列内事件全部处理完毕才退出。要规定事件怎样处理就要编写规则文件了.规则文件是udev的灵魂,没有规则文件,udev无法自动加载硬件设备的驱动模块。它一般位于3初始化段的应用这里给出一个简单的初始化段的使用例子,将a.c编译成一个动态库,其中,函数a()和函数c()放在两个不同的初始化段里,函数b()默认放置;编译main.c,链接到由a.c编译成的动态库,观察各函数的执行顺序。# cat a.c #include typedef int (*fn) (void);int a(void) printf(an); return 0;_attribute_(_secti

14、on_(.init_array.2) static fn init_a = a;int c(void) printf(cn); return 0;_attribute_(_section_(.init_array.1) static fn init_c = c;int b() printf(bn); return 0; # cat main.c#includeint b();int main() printf(mainn); b(); # cat mk.shgcc -fPIC -g -c a.cgcc -shared -g -o liba.so a.ocp liba.so /lib/ -frgcc main.c liba.so ldconfig ./a.out # gcc -fPIC -g -c a.c# gcc -shared -g -o liba.so a.o# cp liba.so /lib/# gcc main.c liba.so # ldconfig # ./a.out acmainb

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1