Linux kernel 分析之十三:kbuild系统-编译到内核和编译成模块的区别
2015-07-22 22:44
573 查看
代码编译到内核和编译成模块在代码中有什么区别呢?
从模块的代码中看是一样的。入口函数都是module_init(fun),但是代码中的条件编译会使宏module_init()在编译到内核和编译成模块的情况下替换成不同的代码。
include/linux/init.h中可知#ifndef MODULE...
#define module_init(x) __initcall(x);...
#else /* MODULE */...
/* Each module must use one module_init(), or one no_module_init */
#define module_init(initfn) \ static inline initcall_t __inittest(void) \ { return initfn; } \ int init_module(void) __attribute__((alias(#initfn)));...#endif
当代码编译成模块时,会定义MODULE宏,否则不会。因为在/usr/src/linux/Makefile中可以看到
336 MODFLAGS = -DMODULE337 CFLAGS_MODULE = $(MODFLAGS)338 AFLAGS_MODULE = $(MODFLAGS)
这两个变量又被export成为全局变量。所以可以知道,在编译成模块时,会有MODULE这个宏。
由以下代码可以知道
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn)085 #define __define_initcall(level,fn) \
086 static initcall_t __initcall_##fn __attribute_used__ \087 __attribute__((__section__(".initcall" level ".init"))) = fn
前者实际上是编译入内核中的.initcall6.init 这个section而在
arch/i386/kernel/vmlinux.lds.S中可以知道:083 __initcall_start = .;
084 .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {085 *(.initcall1.init)
086 *(.initcall2.init) 087 *(.initcall3.init) 088 *(.initcall4.init) 089 *(.initcall5.init) 090 *(.initcall6.init) 091 *(.initcall7.init)092 }
093 __initcall_end = .;arch/i386/kernel/vmlinux.lds.S
.initcall6.init是.initcall.init的一部分执行顺序:
start_kernel->rest_init
系统启动后在rest_init中会创建init内核线程init->do_basic_setup->do_initcalls
do_initcalls中会把.initcall.init中的函数依次执行一遍
for (call = __initcall_start; call < __initcall_end; call++) {
...(*call)();...
}
于是执行了module_init(fn)函数
从模块的代码中看是一样的。入口函数都是module_init(fun),但是代码中的条件编译会使宏module_init()在编译到内核和编译成模块的情况下替换成不同的代码。
include/linux/init.h中可知#ifndef MODULE...
#define module_init(x) __initcall(x);...
#else /* MODULE */...
/* Each module must use one module_init(), or one no_module_init */
#define module_init(initfn) \ static inline initcall_t __inittest(void) \ { return initfn; } \ int init_module(void) __attribute__((alias(#initfn)));...#endif
当代码编译成模块时,会定义MODULE宏,否则不会。因为在/usr/src/linux/Makefile中可以看到
336 MODFLAGS = -DMODULE337 CFLAGS_MODULE = $(MODFLAGS)338 AFLAGS_MODULE = $(MODFLAGS)
这两个变量又被export成为全局变量。所以可以知道,在编译成模块时,会有MODULE这个宏。
由以下代码可以知道
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn)085 #define __define_initcall(level,fn) \
086 static initcall_t __initcall_##fn __attribute_used__ \087 __attribute__((__section__(".initcall" level ".init"))) = fn
前者实际上是编译入内核中的.initcall6.init 这个section而在
arch/i386/kernel/vmlinux.lds.S中可以知道:083 __initcall_start = .;
084 .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {085 *(.initcall1.init)
086 *(.initcall2.init) 087 *(.initcall3.init) 088 *(.initcall4.init) 089 *(.initcall5.init) 090 *(.initcall6.init) 091 *(.initcall7.init)092 }
093 __initcall_end = .;arch/i386/kernel/vmlinux.lds.S
.initcall6.init是.initcall.init的一部分执行顺序:
start_kernel->rest_init
系统启动后在rest_init中会创建init内核线程init->do_basic_setup->do_initcalls
do_initcalls中会把.initcall.init中的函数依次执行一遍
for (call = __initcall_start; call < __initcall_end; call++) {
...(*call)();...
}
于是执行了module_init(fn)函数
相关文章推荐
- 转载
- Linux kernel 分析之十二:kbuild系统-内核模块的编译
- Linux kernel 分析之十一:信号通信
- 每天一个linux命令(8):cp 命令
- linux下动态库的编写和调用
- linux安装
- Linux下php5.3.6的安装:checking whether libxml build works... no
- linux 小记
- 嵌入式linux之定时器防抖
- linux 命令之 dmidecode
- Linux中的ulimit命令简介(某公司社招笔试试题)
- linux系统配置sftp服务器详解
- Linux kernel 分析之十:内核线程
- Linux kernel 分析之九:fork()系统调用
- linux中的lsof命令简介(某公司社招笔试试题)
- RHEL一(管理文件、通配符、特殊符号)
- Linux目录结构及文件基本操作
- linux patch 命令小结
- linux 日志服务器的构建
- linux文件压缩与解压