各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)【转】
转自:http://www.cnblogs.com/superlcc/archive/2012/09/12/2681930.html
现在以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的执行时刻了吧。
各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)【转】的更多相关文章
- Java中的继承与静态static等的执行先后顺序
package extend; public class X { Y y=new Y(); static{ System.out.println("tttt"); } X(){ ...
- Oracle执行计划顺序
先从最开头一直往右看,直到看到最右边的并列的地方,对于不并列的,靠右的先执行:对于并列的,靠上的先执行. 即并列的缩进块,从上往下执行,非并列的缩进块,从下往上执行. 如下示例: Execu ...
- Spring切面通知执行的顺序(Advice Order)
问题描述 如果在Spring的程序中同时定义了环绕通知(Around)和前置通知(Before)..那么,有以下问题: 1.怎么让两个切面通知都起作用 2.或者让两者切面按自己指定的顺序进行执行? 3 ...
- spring通知执行的顺序
点击下载本示例相关代码 关于spring aop的具体使用,暂时不在这里讲解,后面会特定来讲解,本次主要探讨spring中通知执行的顺序. spring中通知分为以下几种: before:前置通知,在 ...
- throw和throws的区别以及try,catch,finally在有return的情况下执行的顺序
一,抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. (1).系统自动抛异常 1.当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出 ...
- mysql 中语句执行的顺序以及查询处理阶段的分析
原文链接:http://www.php.cn/mysql-tutorials-408865.html 本篇文章给大家带来的内容是关于mysql中语句执行的顺序以及查询处理阶段的分析,有一定的参考价值, ...
- spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序)
转载:spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序) 众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执 ...
- JavaScript执行优先顺序
js在html中的加载执行顺序 1.加载顺序:引入标记<script />的出现顺序, 页面上的Javascript代码是HTML文档的一部分,所以Javascript在页面装载时执行的顺 ...
- Python+selenium之unittest单元测试(3)关于测试用例执行的顺序
一.测试用例执行的顺序 用例的执行顺序涉及多个层级,在多个测试目录的情况下,先执行哪个目录?在多个测试文件的情况下,先执行哪个文件?在多个测试类的情况下,先执行哪个测试类?,在多个测试方法(用例)的情 ...
随机推荐
- 弟三周作业之VS2015
这周有个任务就是安装VS2015,然后进行简单的单元测试. 首先我上吴小勇同学给的MSDN官网(http://www.itellyou.cn/)下载VS2013, 然后装上后,在工具栏里,点击工具里的 ...
- [菜鸟]HTTP 与 HTTPS 的区别
HTTP 与 HTTPS 的区别 分类 编程技术 基本概念 HTTP(HyperText Transfer Protocol:超文本传输协议)是一种用于分布式.协作式和超媒体信息系统的应用层协议. 简 ...
- Helm 安装 nginx-ingress 的方法
还是没学会 今天继续研究. Using Helm NGINX Ingress controller can be installed via Helm using the chart stable/n ...
- ehcache、redis应用场景比较
应用场景: ehcache是Hibernate中默认的CacheProvider,直接在jvm虚拟机中缓存,速度快,效率高:但是缓存共享麻烦,集群分布式应用不方便. . 缓存数据有两级:内存和磁盘, ...
- Ubuntu17安装MySql5.7
安装: sudo apt-get update sudo apt-get install mysql-server 配置远程访问: vi /etc/mysql/mysql.conf.d/mysqld. ...
- The Super Powers UVA - 11752(合数幂)
题意: 求1~2^64-1之间所有的 至少是两个不同的正整数的幂的数 升序输出 一个数的合数次幂即为这样的数 找出1~2^64-1中所有数的合数次幂 用set存起来(既能防止重复 又能升序) 最后输 ...
- tomcat Failed creating java C:\Program Files\Java\jre6\bin\client\jvm.dll %1 不是有效的 Win32 应用程序。
jdk版本搞的鬼 请下载64位的jdkj进行安装
- 一台机子同时启动两个相同版本的tomcat
其实我的机子之前是可以同时启动两个tomcat的,但是是两个不同版本的tomcat,一个是6.0,一个是7.0,我的环境变量都没有设置,所以我对解压过的tomcat唯一改动的就是在catalina.b ...
- ARG102E:Stop. Otherwise...
传送门 Sol 对于每个 \(i\) ,可以把 \(k\) 个数字分成 \((x,i-x)\) 的若干组. 那么就是求每组只能其中选择一个且可以重复的方案数. 预处理 \(f[i][j]\) 表示从 ...
- 洛谷 P1457 城堡 The Castle 解题报告
P1457 城堡 The Castle 题目描述 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张"幸运爱尔兰" ...