您的位置:首页 > 运维架构 > Linux

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐