postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
来源:互联网 发布:java web图书管理系统 编辑:程序博客网 时间:2024/05/17 22:52
http://blog.csdn.net/thl789/article/details/6581146
在内核源代码中,platform 设备的初始化(注册)用arch_initcall()调用,它的initcall 的level为3;而驱动的注册用module_init()调用,即device_initcall(),它的initcall 的level为6。#define module_init(x) __initcall(x);#define __initcall(fn) device_initcall(fn) kernel 初始化时(kernel_init@init/main.c),按照内核链接文件中(arm系统:kernel/arch/arm/vmlinux.lds)的__init call_start段的序列依次执行,这样level小的初始化函数先于level大的初始化函数被调用。 所以platform设备先被注册,驱动加载时会调用驱动程序中的probe(),扫描系统中已注册的设备,找到匹配设备后将驱动和设备绑定。
比如I2C,适配器先需要 设备注册;
=============================
LINUX内核中有很多的初始化指示标志postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall(), etc. 这些起什么作用呢?
- 初始化标号
先看这些宏的定义(定义在文件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)
2、__define_initcall
这些宏都用到了__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的含义是:
1) 声明一个名称为__initcall_##fn的函数指针;
2) 将这个函数指针初始化为fn;
3) 编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中。
3.放置.initcall.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)
__initcall_start和__initcall_end以及INITCALLS中定义的SECTION都是在arch/xxx/kernel/vmlinux.lds.S中放在.init段的。
- SECTIONS
- {
- .init : {
- __initcall_start = .;
- INITCALLS
- __initcall_end = .;
- }
- }
4. 初始化.initcallxx.init里的函数
而这些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/fenzhikeji/article/details/6860143
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- 各种initcall的执行先后顺序(module_init、postcore_initcall、arch_initcall、subsys_initcall、 fs_initcall)
- module_init/subsys_initcall/postcore_initcall 执行顺序。
- subsys_initcall
- subsys_initcall
- subsys_initcall
- subsys_initcall
- 项目——银行业务调度系统
- 获取手机联系人信息(姓名 电话号码)
- unix环境编程卷2之System V共享内存
- 【Java】Treeset实现自定义排序
- [转]C++ const变量使用技巧总结
- postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall() 调用顺序
- 经典逻辑思维问题及答案
- gethibernatetemplate find条件查询方法
- Reading Plan
- SIFT之二:获取精确特征点位置
- 在数据库各种状态下查询DBID的五大类十种方法汇总
- 统计-5 事件关系
- delphi 调用dll两种方式
- rqnoj-396-SY学语文-dp