2024年4月28日发(作者:)

Initcall 的实现

initcall是内核提供的一种挂接机制,利用这种机制可以让内核在特定的时刻调用自

己,例如,某些驱动程序就有这种需要。

typedef int (*initcall_t)(void);

#define __define_initcall(level,fn,id)

static initcall_t __initcall_##fn##id __attribute_used__

__attribute__((__section__(".initcall" level ".init"))) = fn

level的合理取值为0-7,0s-7s(2.6.19.2)

数值小的将排在前面,相同数值的s排在非s后面

/*

* A "pure" initcall has no dependencies on anything else, and purely

* initializes variables that couldn't be statically initialized.

*

* This only exists for built-in code, not for modules.

1

*/

#define pure_initcall(fn) __define_initcall("0",fn,1)

#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 device_initcall(fn) __define_initcall("6",fn,6)

2

#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)

内核调用链

start_kernel -> rest_init -> init -> do_basic_setup -> do_initcalls

1,所有可以initcall的函数都必须符合下面形式

int foo(void);

2,__define_initcall宏导出函数到内核映像的.段

__define_initcall("1",foo,1)或core_initcall(foo)

展开后形成如下申明

static initcall_t __initcall_foo1 __attribute_used__

__attribute__((__section__("."))) = foo;

所有的申明形成一个initcall_t数组

3

3,内核在do_initcalls函数中历遍该数组

static void __init do_initcalls(void)

{

...

for (call = __initcall_start; call < __initcall_end; call++) {

...

//对启动参数initcall_debug的支持

if (initcall_debug) {

printk("Calling initcall 0x%p", *call);

print_fn_descriptor_symbol(": %s()",

(unsigned long) *call);

printk("n");

}

4

result = (*call)();

...

}

}

4,驱动中用到的重要申明module_init(x)实际就是initcall的特化:

#define module_init(x) __initcall(x);

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn) __define_initcall("6",fn,6)

5