linux initcall 介绍 (转自http://blog.csdn.net/fenzhikeji/article/details/6860143)
现在以module_init为例分析initcall在内核中的调用顺序
在头文件init.h中,有如下定义:
#define module_init(x) __initcall(x);
很明显,module_init()只是一个面具而已,揭开这个面具,下面藏着的是__initcall()
__initcall()又是何方神圣呢?继续揭露真相:
#define __initcall(fn) device_initcall(fn)
藏得真深,继续看:
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
最终我们看到的是module_init的真身:__define_initcall(level,fn,id),仔细 推敲这个真身,知道这是个宏,它把传给module_init的函数名组装成以__initcall为前缀的、以6为后缀的函数名,并把这个函数定义到代 码段.initcall6.init里面。
在代码段.initcall6.init里面?这函数躲在这里干嘛,啥时候才轮得到它出头啊!找到有此字符串的文件vmlinux.lds.h,相关代码如下所示:
#define INITCALLS \
*(.initcallearly.init) \
VMLINUX_SYMBOL(__early_initcall_end) = .; \
*(.initcall0.init) \
*(.initcall0s.init) \
*(.initcall1.init) \
*(.initcall1s.init) \
*(.initcall2.init) \
*(.initcall2s.init) \
*(.initcall3.init) \
*(.initcall3s.init) \
*(.initcall4.init) \
*(.initcall4s.init) \
*(.initcall5.init) \
*(.initcall5s.init) \
*(.initcallrootfs.init) \
*(.initcall6.init) \
*(.initcall6s.init) \
*(.initcall7.init) \
*(.initcall7s.init)
要命,又是一个陌生的宏,不过还好的是他样子看起来还不难看,而且好找规律,看看这是个什么样的东西呢?
字符串.initcall6.init夹杂在这个宏的第n行,具体自己数,他们挨个挨个有顺序的组成一个整体,此整体又构成一个用大写字母写的宏INITCALLS,从气势看这个东西给人牛逼的感觉,这么神奇,那他在那里高就呢?
坑爹的,踏破铁鞋无觅处,得来非常费工夫,他竟然在一个偏僻的vmlinux.lds.S里面!估计超出来好多童鞋可以 接受的范围吧,这还不算,这还是个汇编文件!哎,不管怎样,追根述源顺藤摸瓜找到了INITCALLS的娘家,却发现这是个完全陌生的世界!蛋蛋为此疼了 好久,最终还是鼓起来武松打虎的勇气依然闯了进去。人说绝望之后就会有希望,柳暗之后又是一村,哥哥我满眼噙着泪水的发现他们是有人情味的!这个激动啊, 不是三言两语可以说得清的,来看看INITCALLS她娘家房子咋样:
…………省略一大段………….
__initcall_start = .;
INITCALLS
__initcall_end = .;
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
__security_initcall_start = .;
*(.security_initcall.init)
__security_initcall_end = .;
…………省略一大段……………
是不是觉得这还是有点人道主义的,不会像阿拉伯为或藏文一样让你想跳楼吧,来认识一下它的三大姑二大婆吧,对于像 __initcall_start = .与__initcall_end = .之类狐假虎威的家伙咱们初来乍到时吃过他不少亏,印象是相当深刻的,一眼就瞅见它的衰样了,这里的小点不就是代表当前地址吗,一个等号不就是把点代表的 当前地址付给了左边的变量啦,这难不倒已经有两把刷子的我的,照此看来,估摸着__initcall_start与__initcall_end会有同伙 在.c文件里面和他们暗通款曲狼狈为奸,待会再好好戏耍它一番,先pass了,接着看看还有啥新鲜的,嗯?没了,还是回头吧,没苦我一般是不会自找来尝 的,甜头嘛另当别论啦,哈哈哈,
言归正传,INITCALLS在__initcall_start = .与__initcall_end = .之间,表示INITCALLS宏内涵的相关段代码顺序存放在这里,module_init所代表段的镶嵌其中,等候挨个轮到自己被光顾,从 INITCALLS的内容看它被访问的时刻排得还是挺后的,那么其他的又是何方圣神呢?其看下面分解:
#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) __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",fn,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_initcall(fn) __define_initcall("7",fn,7)
#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
至此我们应该明白了各个initcall是如何来的以及在代码存储空间上是怎么组织的了吧,下面来看看内核是什么时候调用它的。
内核启动流程如下所示
Main()àlinux_main()àstart_uml()àstart_kernel_proc()àstart_kernelàrest_inità kernel_inità do_basic_setupà do_initcalls
do_initcalls的代码如下所示
static void __init do_initcalls(void)
{
initcall_t *call;
for (call = __early_initcall_end; call < __initcall_end; call++)
do_one_initcall(*call);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
上面的代码中,__early_initcall_end在INITCALLS内定义,__initcall_end在 文件vmlinux.lds.S中定义,他们代表的是一些初始化函数的指针数组起始与结束地址,执行函数do_initcalls时,包含在这各指针数组 里面的函数顺序的被调用以执行一些必要的初始化工作。至此,明白的各initcall的执行时刻了吧。
linux initcall 介绍 (转自http://blog.csdn.net/fenzhikeji/article/details/6860143)的更多相关文章
- 【solr filter 介绍--转】http://blog.csdn.net/jiangchao858/article/details/54989025
Solr的Analyzer分析器.Tokenizer分词器.Filter过滤器的区别/联系 Analyzer负责把文本字段转成token stream,然后自己处理.或调用Tokenzier和Filt ...
- Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79530732
Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79 ...
- http://blog.csdn.net/luoshengyang/article/details/6651971
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6651971 在Android系统中,提供了独特 ...
- http://blog.csdn.net/zhanglvmeng/article/details/11928469
本系列主要结合<PHP和MYSQL WEB开发 第四版>,在阅读中提出自己认为比较重要的一些问题,以加深对知识的了解程度. 1.简短.中等以及冗长风格的表单变量 $name; //简短风格 ...
- matplotlib绘图基本用法-转自(http://blog.csdn.net/mao19931004/article/details/51915016)
本文转载自http://blog.csdn.net/mao19931004/article/details/51915016 <!DOCTYPE html PUBLIC "-//W3C ...
- git创建使用1https://blog.csdn.net/Hanani_Jia/article/details/77950594
这篇文章是我自己写的关于GitHub的内容,从我刚听到这个直到设置成功每一步都有详细的步骤来解释,其中有一些截图或者代码来自于网上. 首先,我先对GitHub来一个简单的介绍,GitHub有一个很强大 ...
- http://blog.csdn.net/LANGXINLEN/article/details/50421988
GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地 ...
- matlab 降维工具 转载【https://blog.csdn.net/tarim/article/details/51253536】
降维工具箱drtool 这个工具箱的主页如下,现在的最新版本是2013.3.21更新,版本v0.8.1b http://homepage.tudelft.nl/19j49/Matlab_Toolb ...
- 【转】【mysql面试】https://blog.csdn.net/hanfazy/article/details/14520437
公司招聘MySQL DBA,也面试了10个2年MySQL DBA工作经验的朋友,谈谈自己的心得,欢迎大家指点. 1 2年MySQL DBA经验 其中许多有水分,一看到简历自我介绍,说公司项目的时 ...
随机推荐
- Guide: Solr performance tuning--转载
原文地址:http://h3x.no/2011/05/10/guide-solr-performance-tuning Introduction I have for the last year be ...
- BZOJ5073 小A的咒语(动态规划)
设f[i][j][0/1]为前i位选j段时其中第i位选/不选最多能匹配到哪,转移时f[i][j][0]→f[i+1][j][0],f[i][j][1]→f[i+1][j][0],f[i][j][1]→ ...
- OSPF协议介绍及配置 (上)
OSPF协议介绍及配置 (上) 一.OSPF概述 回顾一下距离矢量路由协议的工作原理:运行距离矢量路由协议的路由器周期性的泛洪自己的路由表,通过路由的交互,每台路由器都从相邻的路由器学习到路由,并且加 ...
- P1939 【模板】矩阵加速(数列)
题目描述 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1] (x>3) 求a数列的第n项对1000000007(10^9+7)取余的值. 输入输出格式 输入格式: 第一行一 ...
- 洛谷P3938 斐波那契
题目戳 题目描述 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行 繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子 ...
- DjangoORM使用mysql注意
注意事项1:需要在project下的setting里面做设置.让Django生成MySQL类型的数据库. 注意事项2:在Django内部,连MySQL的时候,需要添加下面2句代码: 4.******* ...
- 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 解题报告
P4093 [HEOI2016/TJOI2016]序列 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一 ...
- Dll劫持漏洞详解
一.dll的定义 DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型.在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分 ...
- nginx服务器去掉url中的index.php 和 配置path_info
隐藏index.php server { listen 80; server_name yourdomain.com; root /home/yourdomain/www/; index index. ...