一、背景:
1.系统可见设备、应用可访问设备,需要具备设备文件节点,设备驱动
2.所有设备驱动程序静态链接到内核会导致内核过大, 不易运行
二、特点:
1.可安装模块(module)是编译不链接
2.运行后,动态加载到内核中
3.加载 *** 作由内核或者特权用户使用sbin执行
4.机制支持选择CONFIG_MODULES
二、源码分析:
init/main.c
asmlinkage void __init start_kernel(void)
{
...
rest_init();
...
}
staTIc noinline void __init_refok rest_init(void)
{
...
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
...
}
staTIc int __init kernel_init(void * unused)
{
...
do_basic_setup();
...
}
staTIc void __init do_basic_setup(void)
{
...
do_initcalls();
}
staTIc void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
}
#define INITCALLS
*(.initcallearly.init)
VMLINUX_SYMBOL(__early_initcall_end) = .;
*(.initcall0.init)
*(.initcall0s.init)
*(.initcall1.init)
*(.initcall1s.init)
*(.initcall2.init)
*(.initcall2s.init)
*(.initcall3.init)
*(.initcall3s.init)
*(.initcall4.init)
*(.initcall4s.init)
*(.initcall5.init)
*(.initcall5s.init)
*(.initcallrootfs.init)
*(.initcall6.init)
*(.initcall6s.init)
*(.initcall7.init)
*(.initcall7s.init)
#define INIT_CALLS
VMLINUX_SYMBOL(__initcall_start) = .;
INITCALLS
VMLINUX_SYMBOL(__initcall_end) = .;
#define INIT_DATA_SECTION(initsetup_align)
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
INIT_DATA
INIT_SETUP(initsetup_align)
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS
}
即,从init.data段中取出初始化部分的代码,驱动在初始化时期进行加载
module_init(camera_init);
includelinuxinit.h
#define module_init(x) __initcall(x);
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id)
static initcall_t __initcall_##fn##id __used
__attribute__((__section__(".initcall" level ".init"))) = fn
此处与系统启动加载时期对应,即将驱动代码放入.initcall" level ".init段
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)