刚下了一份2.6.16的kernel,比情景分析中的讲解变得太多了,在/init/main.c中,start_kernel创建了init核心进程后,没找到网络模块的调用入口.???那就反向来吧,找af_inet.c中输出了什么东西让kernel可以调用.呵呵,inet_init,这个是不用怀疑吧,可是用source in sight搜索了整个工程,都没看到调用了inet_init.???
在inet_init后紧接着是:module_init(inet_init);声明成模块了,可以静态连入kernel也可做为module动态insmod.
而在include/linux/init.h中将module_init 声明为:#define module_init(x) __initcall(x);而__initcall又声明为#define __initcall(fn) device_initcall(fn);而device_initcall为#define device_initcall(fn) __define_initcall("6",fn);__define_initcall为#define __define_initcall(level,fn) /
static initcall_t __initcall_##fn __attribute_used__ /
__attribute__((__section__(".initcall" level ".init"))) = fn
在arch/i386/kernel/vmlinux.lds.s中定义了initcall.init这样一个section:如下:
__initcall_start = .;
.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
}
__initcall_end = .;
也就是说当将一个原本由init()显示调用的function声明为module后,其module_init函数会ld在链接时,会根据其优先级??(1为core_initcall,2为postcore_initcall,在init.h中有相应定义)链接到initcall.init 这个section中相应位置,越靠前就越先执行.(还是对ld不熟). :(
这样具体再来看:start_kernel() --->init() ---->do_basic_setup() --->do_initcalls();
这个就是一部分do_initcalls的代码了,
static void __init do_initcalls(void)
{
initcall_t *call;
for (call = __initcall_start; call < __initcall_end; call++) {
....
(*call)();
}
在这段代码中,从initcall.init 节中取出所有的initcall,其实就是4个byte的function pointer,再执行.很容易看出来,core_initcall比device_initcall要优先级高些. :)
随手记下的一些笔记,如有错误,麻烦指正,共同进步.