late_initcall

来源:互联网 发布:解矩阵方程ax b x 编辑:程序博客网 时间:2024/06/05 06:27

内核驱动初始化顺序:

内核第一个C函数 main.c/

start_kernel() ---> rest_init() ---> kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND) ---> kernel_init() ---> do_basic_setup() ---> do_initcalls() ---> do_one_initcall()  (initcall fn)  ret = fn();

   

linux-3.4\init

#define __define_initcall(level,fn,id) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(".initcall" level ".init"))) = fn
#define pure_initcall(fn)__define_initcall("0",fn,0)#define core_initcall(fn)__define_initcall("1",fn,1)#define core_initcall_sync(fn)__define_initcall("1s",fn,1s)#define postcore_initcall(fn)__define_initcall("2",fn,2)#define postcore_initcall_sync(fn)__define_initcall("2s",fn,2s)#define arch_initcall(fn)__define_initcall("3",fn,3)#define arch_initcall_sync(fn)__define_initcall("3s",fn,3s)#define subsys_initcall(fn)__define_initcall("4",fn,4)#define subsys_initcall_sync(fn)__define_initcall("4s",fn,4s)#define fs_initcall(fn)__define_initcall("5",fn,5)#define fs_initcall_sync(fn)__define_initcall("5s",fn,5s)#define rootfs_initcall(fn)__define_initcall("rootfs",fn,rootfs)#define device_initcall(fn)__define_initcall("6",fn,6)#define device_initcall_sync(fn)__define_initcall("6s",fn,6s)#define late_initcall(fn)__define_initcall("7",fn,7)#define late_initcall_sync(fn)__define_initcall("7s",fn,7s)

pci-driver.c

postcore_initcall(pci_driver_init);
static initcall_t __initcall_pci_driver_init2 __attribute__((__used__)) \      __attribute__((__section__(".initcall2.init"))) = pci_driver_init;  

调用宏产生相应的函数指针变量,这些变量并被链接到相应的名称如 .initcall<level>[s].init 的section


linux-3.4\initmain.c

static void __init do_initcalls(void){int level;for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)do_initcall_level(level);}
static void __init do_initcall_level(int level){extern const struct kernel_param __start___param[], __stop___param[];initcall_t *fn;strcpy(static_command_line, saved_command_line);parse_args(initcall_level_names[level],   static_command_line, __start___param,   __stop___param - __start___param,   level, level,   repair_env_string);for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)do_one_initcall(*fn);}


int __init_or_module do_one_initcall(initcall_t fn){int count = preempt_count();int ret;if (initcall_debug)ret = do_one_initcall_debug(fn);elseret = fn();..........}




linux-3.4\include\asm-generic\vmlinux.lds.h

#define INIT_CALLS_LEVEL(level)\VMLINUX_SYMBOL(__initcall##level##_start) = .;\*(.initcall##level##.init)\*(.initcall##level##s.init)\

#define INIT_CALLS\VMLINUX_SYMBOL(__initcall_start) = .;\*(.initcallearly.init)\INIT_CALLS_LEVEL(0)\INIT_CALLS_LEVEL(1)\INIT_CALLS_LEVEL(2)\INIT_CALLS_LEVEL(3)\INIT_CALLS_LEVEL(4)\INIT_CALLS_LEVEL(5)\INIT_CALLS_LEVEL(rootfs)\INIT_CALLS_LEVEL(6)\INIT_CALLS_LEVEL(7)\VMLINUX_SYMBOL(__initcall_end) = .;


device.h
#define class_create(owner, name) \
({ \
static struct lock_class_key __key;\
__class_create(owner, name, &__key);\

})


devfs不复存在,udev成为devfs的替代。提醒一点,udev是应用层的,不要试图在内核的配置选项里找到它;加入对udev的支持很简单。在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用device_create创建对应的设备。


内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。