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. 文件系统的注册 这里的文件系统是指可能会被挂载到目录树中的各个实际文件系统,所谓 ... 
随机推荐
- Java_Web _Servlet生命周期实验
			第一次加载这个servlet程序时(选择右边的servlet程序,注意servlet程序没有main函数,因此执行的是run as servlet Application ),同时执行init()方法 ... 
- wpf ListBox或ListView等数据控件 绑定数据,最简单的方式
			在网上很难找最简单的案例,都是一大片,看着都头疼: 试试举一反三,如果把结果赋给DataContext这个属性,那就前台需要绑定ItemsSource="{Binding}",请注 ... 
- textLayout在快速输入清除时报错解决方法
			var tf:TextFlow; var len:int = tf.numChildren;for (var i:int = 0; i < len; i += 1){ tf.removeChil ... 
- Linux C 程序 基础语法(1)
			1.Linux 下第一支C程序,控制台打印一句话. vi first.c //linux新建文件 #include<stdio.h> int main() { printf("w ... 
- gdb提示Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.2.x86_64
			用gdb debugc代码的时候弹出这个错误 Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.2. ... 
- 51nod1046快速幂取余
			给出3个正整数A B C,求A^B Mod C. 例如,3 5 8,3^5 Mod 8 = 3. Input 3个正整数A B C,中间用空格分隔.(1 <= A,B,C <= 10^ ... 
- CentOS 6.5升级Python后yum不可用的解决方案
			因开发需要,今天把CentOS 6.5自带的Python2.6.6升级到了Python2.7.3.按照如下步骤进行升级 1.查看当前系统python的版本 python -V 2.下载2.7.3版本的 ... 
- Window_Open详解
			Window_Open详解 引:Window_Open详解一.window.open()支持环境:JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二. ... 
- Erlang 开发者的福音:IntelliJ IDEA 的 Erlang 插件
			IntelliJ IDEA 的 Erlang 插件,主要特性: 智能编辑器: Erlang 代码补全.语法和错误高亮.代码检查 代码导航:项目和文件结构视图.在文件.模型.函数和用例之间快速跳转 工 ... 
- PHPCMS 核心代码与 www 分离部署
			为了满足更多用户二次开发的兴趣与爱好,同时,为了更加安全.可以通过修改入口代码的包含方式来让主程序和www程序分开. 先看下面目录结构: (图1) 我们需要将 phpcms 目录和 index.php ... 
