今天在看内核中无线的实现时,发现一个调用 subsys_initcall(cfg80211_init);搜索一些资料:

subsys_initcall 的定义在 include/linux/init.h 中,定义如下:

#define core_initcall(fn)       __define_initcall(fn, 1)
#define core_initcall_sync(fn)    __define_initcall(fn, 1s)
#define postcore_initcall(fn)        __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn)       __define_initcall(fn, 3)
#define arch_initcall_sync(fn)      __define_initcall(fn, 3s)
#define subsys_initcall(fn)     __define_initcall(fn, 4)
#define subsys_initcall_sync(fn)  __define_initcall(fn, 4s)
#define fs_initcall(fn)         __define_initcall(fn, 5)
#define fs_initcall_sync(fn)        __define_initcall(fn, 5s)
#define rootfs_initcall(fn)          __define_initcall(fn, rootfs)
#define device_initcall(fn)          __define_initcall(fn, 6)
#define device_initcall_sync(fn)  __define_initcall(fn, 6s)
#define late_initcall(fn)             __define_initcall(fn, 7)
#define late_initcall_sync(fn)     __define_initcall(fn, 7s)

查看宏定义 _define_initcall 定义在同一个文件中(include/linux/init.h)

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

定义了一个函数指针赋值的实现,    __initcall_##fn##id  函数的实现为  fn函数;编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中。

明确了__define_initcall的含义,就知道了是分别将这些初始化标号修饰的函数指针放到各自的section中的。

SECTION“.initcall”level”.init”被放入INIT_CALLS(include/asm-generic/vmlinux.lds.h)(内核3.10.14)

#define INIT_CALLS       \
  VMLINUX_SYMBOL(__initcall_start) = .;   \
  *(.initcallearly.init)     \
  INIT_CALLS_LEVEL(0)     \
  INIT_CALLS_LEVEL(1)     \
  INIT_CALLS_LEVEL(2)     \
  INIT_CALLS_LEVEL(3)     \
  INIT_CALLS_LEVEL(4)     \
  INIT_CALLS_LEVEL(5)     \
  INIT_CALLS_LEVEL(rootfs)    \
  INIT_CALLS_LEVEL(6)     \
  INIT_CALLS_LEVEL(7)     \
  VMLINUX_SYMBOL(__initcall_end) = .;

__initcall_start和__initcall_end以及INITCALLS中定义的SECTION都是在arch/xxx/kernel/vmlinux.lds.S中放在.init段的。

  1. SECTIONS
  2. {
  3. .init : {
  4. __initcall_start = .;
  5. INITCALLS
  6. __initcall_end = .;
  7. }
  8. }

而这些SECTION里的函数在初始化时被顺序执行(init内核线程->do_basic_setup()[main.c #778]->do_initcalls())。

程序(init/main.c文件do_initcalls()函数)如下,do_initcalls()把.initcallXX.init中的函数按顺序都执行一遍。

for (call = __early_initcall_end; call < __initcall_end; call++) 
        do_one_initcall(*call);

参考文档  :  http://blog.csdn.net/thl789/article/details/6581146#

转载于:https://www.cnblogs.com/rohens-hbg/p/6524231.html

内核中 subsys_initcall 以及初始化标号相关推荐

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

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

  2. c++ map 初始化_如何调整Linux内核启动中的驱动初始化顺序?

    如何调整Linux内核启动中的驱动初始化顺序?[问题] 此处我要实现的是将芯片的ID用于网卡MAC地址,网卡驱动是enc28j60_init. 但是,读取芯片ID的函数,在as352x_afe_ini ...

  3. Linux内核 eBPF基础:perf(1):perf_event在内核中的初始化

    Linux内核 eBPF基础 perf(1):perf_event在内核中的初始化 荣涛 2021年5月12日 本文相关注释代码:https://github.com/Rtoax/linux-5.10 ...

  4. Linux内核中的xx_initcall

    2019独角兽企业重金招聘Python工程师标准>>> 本文编辑整理自: http://www.linuxidc.com/Linux/2011-09/43354.htm 先看这些宏的 ...

  5. linux标准c和c编译器6,linux内核中GNU C和标准C的区别

    linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...

  6. 详解Linux2.6内核中基于platform机制的驱动模型 (经典)

    [摘要]本文以Linux 2.6.25 内核为例,分析了基于platform总线的驱动模型.首先介绍了Platform总线的基本概念,接着介绍了platform device和platform dri ...

  7. 详解Linux2.6内核中基于platform机制的驱动模型

    原文地址:详解Linux2.6内核中基于platform机制的驱动模型 作者:nacichan [摘要]本文以Linux 2.6.25 内核为例,分析了基于platform总线的驱动模型.首先介绍了P ...

  8. linux中内核中machine_desc,Linux-内核-学习笔记(13):移植三星官方内核

    Linux-内核-学习笔记(13):移植三星官方内核 一.移植前的准备 当拿到源代码时,首先要在window下利用SourceInsight创建一个工程,并将uboot源代码加载到SI中,方便修改和查 ...

  9. 内核中_init,_exit中的作用

    __init, __initdata等属性标志,是要把这种属性的代码放入目标文件的.init.text节,数据放入.init.data节──这一过程是通过编译内核时为相关目标平台提供了xxx.lds链 ...

最新文章

  1. 苹果「热修复门」事件复盘、分析和展望
  2. dojo helloworld
  3. 无法访问本地ip_当金万维异速联无法访问金蝶软件怎么办?
  4. 高效地加载图片(一) 高效地加载大图
  5. JS实现表单多文件上传样式美化支持选中文件后删除相关项
  6. centos php mysql 配置_CentOS系统中安装配置Apache+PHP+MySQL环境
  7. 如何解决局域网共享报错0x80004005
  8. maxscale mysql5.7_Centos7安装maxscale 实现mysql的读写分离
  9. 中国大陆五级行政区划数据爬虫
  10. RAID磁盘阵列管理
  11. 最彻底的健身补剂——肌酸!
  12. 工业物联网(IIoT)生态构建三字经:先做人、后修心、再打怪!
  13. 光学指纹模组解锁方案设计指纹锁方案
  14. 利用RSS进行学术期刊订阅
  15. python换源_python更换国内源
  16. 微软亚洲研究院实习生面试
  17. Web安全之SQL注入漏洞学习(七)-堆叠注入
  18. angularjs 获取复选框的值_加快周期进度,DNF疲劳药获取指南
  19. 西门子PLC的局部变量怎么使用
  20. 手机消息推送之web端开发

热门文章

  1. java命令行参数_Java学习从入门到精通,JDK工具条知识点学习资料
  2. 跨网段远程调试vs_使用 VS 2019 跨平台编写和调试 Linux C/C++程序
  3. 怎么查看linux日志里请求量最高的url访问最多的_LoaRunner性能测试系统学习教程:日志文件分析(8)...
  4. 正整数的唯一分解定理 c语言,SSOJ2662正整数的唯一分解定理
  5. (源码实例)通过层DIV实现,当鼠标放在链接上面,显示图片及文字
  6. MySQL学习笔记:SQL基本语法
  7. HTML学习笔记:实现条纹边框
  8. 【BZOJ1057】【codevs1428】棋盘制作,悬线法
  9. eds800变频器故障代码_干货|三菱变频器故障剖析,及严重故障和轻微故障判断技巧!...
  10. java怎么设置命令行参数_java 命令行参数