2019独角兽企业重金招聘Python工程师标准>>>

本文编辑整理自: http://www.linuxidc.com/Linux/2011-09/43354.htm

先看这些宏的定义(定义在文件include/linux/init.h中)
#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) 
这些宏都用到了__define_initcall(),再看看它的定义(同样定义在文件include/linux/init.h中)

#define __define_initcall(level, fn,id) \  
static initcall_t __initcall_##fn##id __used \ 
__attribute__(( __section__(". initcall" level " .init"))) = fn

这其中 initcall_t 是函数指针,原型如下,
typedef int (*initcall_t)(void); 
而编译器宏 __attribute__((__section__())) 则表示把对象放在一个这个由括号中的名称所指代的section中。
__define_initcall("6",fn,6) 则是把fn的地址放到. initcall 6 . init 这个selection中
另外,注意这里 static 的作用,只是当前编译单元可见,从全局来看的 __initcall_##fn##id 完整名字,是要加当前编译文件名(或称当前编译单位名)作为前缀的
所以__define_initcall的含义是:
1) 声明一个名称为__initcall_##fn的函数指针;
2) 将这个函数指针初始化为fn;
3) 编译的时候需要把这个函数指针变量放置到名称为 ". initcall " level " .init "的section中

明确了 __define_initcall 的含义,就知道了它其实是分别将这些初始化标号修饰的函数指针放到各自的section中的。
SECTION“ .initcall ” level ”. init ”被放入 INITCALLS ( include/asm-generic/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) 
VMLINUX_SYMBOL( __early_initcall_end) =  . ;   这里的   . 是一个特殊的符号,它是定位器,一个位置指针,指向程序地址空间内的某位置(或某section内的偏移,如果它在SECTIONS命令内的某section描述内),该符号只能在SECTIONS命令内使用。
这句命令的意思,是对 __early_initcall_end 变量赋值为 当前section内的偏移
*( .initcall7s.init ) 表示的是 所有输入文件 中的名为 .initcall7s.init 的 SECTIONS
__initcall_start 和 __initcall_end 以及 INITCALLS 中定义的SECTION都是在arch/xxx/kernel/vmlinux.lds.S中放在 .init 段的。
SECTIONS  
        . init : { 
               __initcall_start = .
                       INITCALLS  
                __initcall_end = .
        } 
}
. init 只是用于对 SECTIONS 进行分类 
__initcall_start = . ;  和 __initcall_end = . ;  表示分别对变量 __initcall_start 和 __initcall_end   赋值为 当前section内的偏移。
而这些 SECTION 里的函数在初始化时被顺序执行(init内核线程-> do_basic_setup() [main.c#778]-> do_initcalls() )。
程序( init/main.c 文件 do_initcalls() 函数)如下, do_initcalls() 把 XX.initcallXX.init 中的函数按顺序都执行一遍。
for (call = __early_initcall_end ; call < _ _initcall_end ; call++) 
        do_one_initcall(*call); 

关于SECTION的更多内容请参考《 Linux下的lds链接脚本简介》

转载于:https://my.oschina.net/u/178323/blog/48911

Linux内核中的xx_initcall相关推荐

  1. LINUX内核中的xx_initcall初始化标号

    LINUX内核中的xx_initcall初始化标号 田海立@CSDN 2011-07-02 LINUX内核中有很多的初始化指示标志postcore_initcall(), arch_initcall( ...

  2. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  3. 简单谈一点linux内核中套接字的bind机制--数据结构以及端口确定

    众所周知,创建一个套接字可以bind到一个特定的ip地址和端口,实际上套接字这一概念代表了TCP/IP协议栈的应用层标识,协议栈中的应用层就是通过一个ip地址和一个端口号标识的,当然这仅仅是对于TCP ...

  4. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  5. 如何放出Linux内核中的链表大招

    前言 上回,我们说到Linux内核中max()宏的终极奥义,Linux内核链表也不甘示弱,那么接下来,让我们看看Linux内核中的链表大招. 如何放出Linux内核中的链表大招 前言 一.链表简介 ( ...

  6. Linux内核中max()宏的奥妙何在?(一)

    Linux内核中max()宏的奥妙何在?(一) 1.max()宏那点事 在Linux内核中,有这样四个比较大小的函数,如下: max(x,y) //两个数求最大值 min(x,y) //两个数求最小值 ...

  7. Linux内核中max()宏的奥妙何在?(二)——大神Linus对这个宏怎么看?

    最新max()宏 上回,我们在<Linux内核中max()宏的奥妙何在?(一)>一文中说到,在3.18.34版Linux内核源码中的max()宏,采用了GCC的扩展特性,可以避免一些错误. ...

  8. Linux中文件描述符1,linux内核中的文件描述符(一)--基础知识简介

    原标题:linux内核中的文件描述符(一)--基础知识简介 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blo ...

  9. Linux 内核中的 GCC 特性(zz)

    from:http://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux ...

最新文章

  1. 软件设计模式-7种设计原则总结
  2. 在web html页面中,打印、预览当前页面
  3. bat窗口大小设置_Tomcat的JVM和连接数设置
  4. java jmx 配置_Java JMX远程调优一点就通
  5. 设置IE默认文本模式的方法
  6. secret sharing;拉格朗日插值,shamir秘密分享,peterson秘密分享
  7. 【shell编程】1、shell编程简介
  8. 7.2 HAVING子句
  9. 《嵌入式C编程:PIC单片机和C编程技术与应用》一导读
  10. 支持向量机原理(理解SVM的三层境界)
  11. idea在 keymap下的eclipse的快捷键
  12. [原]产品经理和韦小宝
  13. 简述机器指令与微指令之间的关系_机器指令与微指令有什么联系和区别?
  14. ios系统光遇是什么服务器,光遇什么时候合服?光遇国服安卓和IOS什么时候互通?...
  15. 电脑磁盘右键没有新建文件夹???
  16. 香港、澳门通行证网上申请
  17. 安卓 获取机身内存,可用内存;运行内存,剩余内
  18. Allegro软件操作——绘制完成后检查内容,Gerberout
  19. python中x 什么意思_python中x[::]什么意思
  20. 阿拉丁HASP SRM加密锁(加密狗)

热门文章

  1. C++安全方向(三):3.7 使用openssl_evp接口完成SHA3和国密SM3
  2. gds文件转bmp_OFD文件转换服务
  3. 计算机控制与网络,网络与通信技术在计算机控制的作用
  4. android打开sqlite数据库,Android:打开和关闭SQLite数据库
  5. mysql 比较一个字符串_比较MySQL中的两个字符串?
  6. mysql二进制日志重置_MySQL二进制日志备份和恢复详解
  7. cygwin安装好了如何添加cmake make_在windows上使用cmake
  8. Java Servlet ServletContext
  9. Java Servlet
  10. NumPy 统计方法