module_init函数对做驱动开发的同学是在太熟悉了,但是关于底层的知识可能大家有些不愿去了解,而其中知识对于网络初始化也直接相关,所以先将此分享。
在驱动程序中有module_init函数,该函数定义在文件
include/linux/module.h中(以前好像在include/linux/init.h中),如下。
#define module_init(x) __initcall(x);
该函数是驱动初始化函数入口,在内核启动或模块加载时候执行。每个模块一个module_init函数。
不过module_init只是个宏,声明为__initcall,又声明在arch/um/include/shared/init.h文件中。
#define __initcall(fn) __define_initcall("1", fn)
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
__define_initcall(level,fn)这个宏的作用就是将初始化函数放在".initcall" level ".init"中。
其中##表示连接的意思,__initcall_##fn##id 为__initcall_fn_id
如果fn = test_init,id = 6时,__initcall_##fn##id 为 __initcall_test_init6。(如果是#是字符串化的意思,#id 为“id”,id=6时,#id 为“6”。)
通过__attribute__(__section__)设置函数属性,也就是将test_init放在.initcall6.init段中。这个涉及连接的脚本。
这些宏用于标记一些初始化函数或初始化数。内核在初始化阶段使用这些函数并在之后释放内存资源。
平台设备的初始化(注册)用arch_initcall()调用,initcall的level为3;驱动的注册用module_init调用,即device_initcall,它的initcall 的level为6。
#define pure_initcall(fn) __define_initcall(fn, 0)
#define core_initcall(fn) __define_initcall(fn, 1)
#define core_initcall_sync(fn) __define_initcall(fn, 1s)
#define postcore_initcall(fn) __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn) __define_initcall(fn, 3)
#define arch_initcall_sync(fn) __define_initcall(fn, 3s)
#define subsys_initcall(fn) __define_initcall(fn, 4)
#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)
#define fs_initcall(fn) __define_initcall(fn, 5)
#define fs_initcall_sync(fn) __define_initcall(fn, 5s)
#define rootfs_initcall(fn) __define_initcall(fn, rootfs)
#define device_initcall(fn) __define_initcall(fn, 6)
#define device_initcall_sync(fn) __define_initcall(fn, 6s)
#define late_initcall(fn) __define_initcall(fn, 7)
#define late_initcall_sync(fn) __define_initcall(fn, 7s)
然后会调用do_initcalls函数调用通过xxx_initcall注册的各种函数,优先级高的先执行。所以通过module_init注册的函数在kernel启动的时候会被顺序执行。