linux启动时对编译进内核驱动模块的加载
2013-08-14 16:44
591 查看
linux启动时对编译进内核驱动模块的加载文章来源:http://gliethttp.cublog.cn今天北京下雨了[init/main.c]start_kernel()-rest_init()-kernel_thread创建 ... - Discuz! Board
http://www.cnblogs.com/leaven/archive/2010/03/31/1701260.html
linux启动时对编译进内核驱动模块的加载
文章来源:http://gliethttp.cublog.cn
今天北京下雨了
[init/main.c]start_kernel()->rest_init()->kernel_thread创建核心线程init()->do_basic_setup()->do_initcalls()
static void __init do_initcalls(void)
{
initcall_t *call;
call = &__initcall_start;
do {
(*call)();
call ;
} while (call &__initcall_end);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_tasks();
}
vmlinux-armv.lds.in中对__initcall_start的定义
...
__initcall_start = .;
*(.initcall.init)
__initcall_end = .;
...
/include/linux/init.h中对.initcall.init和initcall_t定义
typedef int (*initcall_t)(void);
#define __init_call __attribute__ ((unused,__section__ (".initcall.init ")))
#define module_init(x) __initcall(x);
在dirvers/at91/net/at91_ether.c中
module_init(at91ether_init)
所以能够看出at91ether_init初始化函数指针将会被连接到.initcall.init空间,因此(*call)();系统启动时核心线程Init将直接调用
at91ether_init()完成网络硬件初始化;对于insmod加载的驱动,任何工作由insmod单独解析完成,insmod系统调用原型为sys_init_module
将rtl8019驱动编译进linux内核
1>驱动代码:rtl8019.c
2>在net目录下的config.in文档中添加一项
dep_tristate ' RTL8019 support' CONFIG_RTL8019 $CONFIG_ISA
3>make menuconfig
将RTL8019 support选择'y',保存退出,autoconf文档中出现一个宏定义:#define CONFIG_RTL8019
4>向net目录下的makefile,添加:
obj-$(CONFIG_RTL8019) = rtl8019.o
5>编译内核,即将rtl8019添加到了linux内核
注:在menuconfig中选择m和y的区别:
y:模块驱动编译到内核中,启动时自动加载
m:模块会被编译,但是不会被编译到内核中,只是生成.o文档,我们能够收集这些.o文档做到linux的文档系统,如:ramdisk中,然后用modprobe或insmod实现动态加载.
==============================================================================================
内核初始化设备驱动的过程:start_kernel()->rest_init()->do_basic_setup()->do_initcalls()
函数do_initcalls如下:
for (call = __initcall_start; call < __initcall_end; call++) {//循环调用__initcall_start与__initcall_end之间函数
.........
result = (*call)();
.........
}
关于module_init的定义如下:
#define __define_initcall(level,fn) \
90 static initcall_t __initcall_##fn __attribute_used__ \
91 __attribute__((__section__(".initcall" level ".init"))) = fn
#define device_initcall(fn) __define_initcall("6",fn)
#define __initcall(fn) device_initcall(fn)
#define module_init(x) __initcall(x);
文件linux/arch/arm/kernel/vmlinux.lds.S 中
__initcall_start = .;
49 *(.initcall1.init)
50 *(.initcall2.init)
51 *(.initcall3.init)
52 *(.initcall4.init)
53 *(.initcall5.init)
54 *(.initcall6.init)
55 *(.initcall7.init)
56 __initcall_end = .;
/include/linux/init.h中对.initcall.init和initcall_t定义
typedef int (*initcall_t)(void);
#define __init_call __attribute__ ((unused,__section__ (".initcall.init ")))
#define module_init(x) __initcall(x);
在dirvers/at91/net/at91_ether.c中
module_init(at91ether_init)
http://www.cnblogs.com/leaven/archive/2010/03/31/1701260.html
linux启动时对编译进内核驱动模块的加载
文章来源:http://gliethttp.cublog.cn
今天北京下雨了
[init/main.c]start_kernel()->rest_init()->kernel_thread创建核心线程init()->do_basic_setup()->do_initcalls()
static void __init do_initcalls(void)
{
initcall_t *call;
call = &__initcall_start;
do {
(*call)();
call ;
} while (call &__initcall_end);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_tasks();
}
vmlinux-armv.lds.in中对__initcall_start的定义
...
__initcall_start = .;
*(.initcall.init)
__initcall_end = .;
...
/include/linux/init.h中对.initcall.init和initcall_t定义
typedef int (*initcall_t)(void);
#define __init_call __attribute__ ((unused,__section__ (".initcall.init ")))
#define module_init(x) __initcall(x);
在dirvers/at91/net/at91_ether.c中
module_init(at91ether_init)
所以能够看出at91ether_init初始化函数指针将会被连接到.initcall.init空间,因此(*call)();系统启动时核心线程Init将直接调用
at91ether_init()完成网络硬件初始化;对于insmod加载的驱动,任何工作由insmod单独解析完成,insmod系统调用原型为sys_init_module
将rtl8019驱动编译进linux内核
1>驱动代码:rtl8019.c
2>在net目录下的config.in文档中添加一项
dep_tristate ' RTL8019 support' CONFIG_RTL8019 $CONFIG_ISA
3>make menuconfig
将RTL8019 support选择'y',保存退出,autoconf文档中出现一个宏定义:#define CONFIG_RTL8019
4>向net目录下的makefile,添加:
obj-$(CONFIG_RTL8019) = rtl8019.o
5>编译内核,即将rtl8019添加到了linux内核
注:在menuconfig中选择m和y的区别:
y:模块驱动编译到内核中,启动时自动加载
m:模块会被编译,但是不会被编译到内核中,只是生成.o文档,我们能够收集这些.o文档做到linux的文档系统,如:ramdisk中,然后用modprobe或insmod实现动态加载.
==============================================================================================
内核初始化设备驱动的过程:start_kernel()->rest_init()->do_basic_setup()->do_initcalls()
函数do_initcalls如下:
for (call = __initcall_start; call < __initcall_end; call++) {//循环调用__initcall_start与__initcall_end之间函数
.........
result = (*call)();
.........
}
关于module_init的定义如下:
#define __define_initcall(level,fn) \
90 static initcall_t __initcall_##fn __attribute_used__ \
91 __attribute__((__section__(".initcall" level ".init"))) = fn
#define device_initcall(fn) __define_initcall("6",fn)
#define __initcall(fn) device_initcall(fn)
#define module_init(x) __initcall(x);
文件linux/arch/arm/kernel/vmlinux.lds.S 中
__initcall_start = .;
49 *(.initcall1.init)
50 *(.initcall2.init)
51 *(.initcall3.init)
52 *(.initcall4.init)
53 *(.initcall5.init)
54 *(.initcall6.init)
55 *(.initcall7.init)
56 __initcall_end = .;
/include/linux/init.h中对.initcall.init和initcall_t定义
typedef int (*initcall_t)(void);
#define __init_call __attribute__ ((unused,__section__ (".initcall.init ")))
#define module_init(x) __initcall(x);
在dirvers/at91/net/at91_ether.c中
module_init(at91ether_init)
相关文章推荐
- linux启动时对编译进内核驱动模块的加载
- 转:linux启动时对编译进内核驱动模块的加载
- Linux 2.6 内核驱动模块的编译和加载
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- Code maturity level options 代码成熟度选项 [*]Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完成的代码与驱动.除非你是测试人员或者开发者,否则请勿选择 我是开发者,所以选[*] Loadable module support 可加载模块支持 [*]Enable loadable module support 内核编译配置选项简介 (2.4.20-8
- 在Linux启动时自动加载内核模块
- Linux 2.6内核的编译步骤及模块动态加载
- 最简单的helloworld模块编译加载(linux3.5内核源码树建立)
- linux 内核模块的编译(用于驱动开发)
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- 【TINY4412】LINUX学习笔记:(2)内核模块编译、安装、加载、卸载
- linux驱动的动态加载和编译内核的方式加载
- 将LED驱动模块编译到Linux3.10.17内核
- Linux如何在系统启动时自动加载内核模块
- Linux 2.6内核的编译步骤及模块的动态加载
- Linux 2.6内核的编译步骤及模块的动态加载
- linux驱动编译进内核或模块配置
- Linux 2.6内核下编译可以加载的内核模块
- Linuxx 2.6内核可加载模块的编译
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程(转)