module_init宏解析
在init.h中我们看到
#define module_init(x) __initcall(x);
还看到
#define __initcall(fn) device_initcall(fn)
还有
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn __attribute_used__ \
__attribute__((__section__(".initcall" level ".init"))) = fn __define_initcall 作用 宏定义__define_initcall(level,fn) 对于内核的初始化很重要,它指示编译器在编译的时候,将一系列初始化函数的起始地址值按照一定的顺序放在一个section中。在内核初始化阶 段,do_initcalls() 将按顺序从该section中以函数指针的形式取出这些函数的起始地址,来依次完成相应的初始化。由于内核某些部分的初始化需要依赖于其他某些部分的初始 化的完成,因此这个顺序排列常常非常重要。
下面将从__define_initcall(level,fn) 宏定义的代码分析入手,依次分析名称为initcall.init的section的结构,最后分析内核初始化函数 do_initcalls()是如何利用宏定义__define_initcall(level,fn)及其相关的衍生的7个宏宏定义,来实现内核某些部分的顺序初始化的。
、分析 __define_initcall(level,fn) 宏定义
) 这个宏的定义位于inlclude\linux\init.h中:
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn \
__attribute__((__section__(".initcall" level ".init"))) \
= fn
其中 initcall_t 是一个函数指针类型:
typedef int (*initcall_t)(void);
而属性 __attribute__((__section__())) 则表示把对象放在一个这个由括号中的名称所指代的section中。
所以这个宏定义的的含义是: () 声明一个名称为__initcall_##fn的函数指针(其中##表示替换连接);
() 将这个函数指针初始化为fn;
() 编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中(比如level="",代表这个section的名称是 ".initcall1.init")。 ) 举例:__define_initcall(, pci_init)上述宏调用的含义是: 声明一个函数指针__initcall_pic_init = pci_init;且
这个指针变量__initcall_pic_init 需要放置到名称为 .initcall6.init的section中( 其实质就是将 这个函数pic_init的首地址放置到了这个section中)。 ) 这个宏一般并不直接使用,而是被定义成下述其他更简单的7个衍生宏这些衍生宏宏的定义也位于 inlclude\linux\Init.h 中: #define core_initcall(fn) __define_initcall("1",fn)
#define postcore_initcall(fn) __define_initcall("2",fn)
#define arch_initcall(fn) __define_initcall("3",fn)
#define subsys_initcall(fn) __define_initcall("4",fn)
#define fs_initcall(fn) __define_initcall("5",fn)
#define device_initcall(fn) __define_initcall("6",fn)
#define late_initcall(fn) __define_initcall("7",fn)
因此通过宏 core_initcall() 来声明的函数指针,将放置到名称为
.initcall1.init的section中,而通过宏 postcore_initcall() 来声明的函数指针,将放置到名称为.initcall2.init的section中,依次类推。 ) 举例:device_initcall(pci_init) 解释同上 -)。 、与初始化调用有关section--initcall.init被分成了7个子section ) 它们依次是.initcall1.init、.initcall2.init、...、.initcall7.init
) 按照先后顺序依次排列
) 它们的定义在文件vmlinux.lds.S中
例如 对于i386+,在i386\kernel\vmlinux.lds.S中有:
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
}
__initcall_end = .;
而在makefile 中有 LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s
) 在这7个section总的开始位置被标识为__initcall_start,而在结尾被标识为__initcall_end。 、 内核初始化函数do_basic_setup(): do_initcalls() 将从.initcall.init
中,也就是这7个section中依次取出所有的函数指针,并调用这些函数指针所指向的函数,来完成内核的一些相关的初始化。
这个函数的定义位于init\main.c中:
//很简单
static void __init do_initcalls(void)
{
......
for (call = __initcall_start; call < __initcall_end; call++) {
......
result = (*call)();
......
}
......
}
module_init宏解析的更多相关文章
- module_init宏解析 linux驱动的入口函数module_init的加载和释放
linux驱动的入口函数module_init的加载和释放 http://blog.csdn.net/zhandoushi1982/article/details/4927579 void free_ ...
- linux 内核驱动编程 简单例子 与_IO, _IOR, _IOW, _IOWR 宏解析
一._IO, _IOR, _IOW, _IOWR 宏的用法与解析 在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值.cmd除了可区别数字外,还包 ...
- container_of宏解析 && 为什么需要使用中间变量__mptr?
#define container_of(ptr, type, member) ({ \ )->member ) *__mptr = (ptr); \ (type *)( (char *)__m ...
- 内核 current宏解析
Technorati 标签: current thread_info 在内核中,可以通过current宏来获得当前执行进程的task_struct指针.现在来简要分析以下: 最原始 ...
- 内核IS_ERR宏解析 【转】
转自:http://blog.chinaunix.net/uid-20196318-id-28769.html 最近在使用filp_open打开文件时遇到到一个问题,当打开一个并不存在的文件时,fil ...
- Linux异常体系之vector_stub宏解析
ARM-Linux汇编的宏定义语法说明如下: 使用注意: 1.宏定义以.macro开始,以.endm结束 2.可带参数,参数可有默认值 3.直接使用参数的名字\arg vector_stub宏的功能: ...
- Linux内核很吊之 module_init解析 (下)【转】
转自:https://blog.csdn.net/richard_liujh/article/details/46758073 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...
- 解析Linux中的VFS文件系统机制
转载:原文地址https://www.ibm.com/developerworks/cn/linux/l-vfs/ 1. 摘要 本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2 ...
- 解析Linux中的VFS文件系统之文件系统的注册(二)
继上一篇文章:http://www.cnblogs.com/linhaostudy/p/7397024.html 3. 文件系统的注册 这里的文件系统是指可能会被挂载到目录树中的各个实际文件系统,所谓 ...
随机推荐
- MBR与分区表备份与恢复
常用工具列表 dd 数据复制,转换实用工具 tar GNU磁盘存档实用工具 cpio 数据存档实用工 ...
- CSS3的几个标签速记1
border-radius:CSS3圆角 语法:border-radius:25px; 椭圆边角:语法-border-radius:xx%;或者15px/100px; box-shadow ...
- 06_XML的写入_dom4j添加、删除、修改Xml文件内容
[工程截图] [person.xml]准备一个xml文件 <?xml version="1.0" encoding="UTF-8"?> <st ...
- windows phone 生产含logo的二维码
这几天了解二维码了解的比较多,不过就是没深入了解.google了一下生产含logo二维码的思路,就是把logo给画到生成的二维码上,还是因为二维码的纠错能力足够好啊,用Graphics对图片进行操作? ...
- mysql 常用命令搜集
查看MYSQL数据库中所有用户及拥有权限 mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query F ...
- leetcode Permutations II 无重全排列
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4051169.html 题目链接:leetcode Permutations II 无重全排 ...
- htmlt中的块状元素与内联元素
块元素(block element) address - 地址 blockquote - 块引用 center - 举中对齐块 dir - 目录列表 div - 常用块级容易,也是CSS layout ...
- C#与.NET
1 .NET Framework的核心是其运行库执行环境,即公共语言运行库(CLR)或.NET运行库,一般将CLR控制下运行的代码称为托管代码(managed code). 在CLR在执行编写好的代码 ...
- iOS之内存管理浅谈
1.何为ARC ARC是automatic reference counting自动引用计数,在程序编译时自动加入retain/release.在对象被创建时retain count+1,在对象被re ...
- 51nod贪心算法入门-----任务分配问题
任务执行顺序 有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i]). 分析: 可以抽象成,从一个整数开始,每次 ...