对 静态编入内核的代码和数据来说,当内核引导时, do_basic_setup()函数调用do_initcalls()函数,后者负责所有.init节函数的执行 。
所有标识为__init的函数在链接的时候都放在.init.text这个区段内,
在这个区段中,函数的摆放顺序是和链接的顺序有关的,是不确定的。
2)
所有的 __init函数在区段.initcall.init中还保存了一份函数指针,
在初始化时内核会通过这些函数指针调用这些__init函数指针,
并在整个初始化完成后,释放整个init区段(包括.init.text,.initcall.init等),
注意,这些函数在内核初始化过程中的调用顺序只和这里的函数指针的顺序有关,
和1)中所述的这些函数本身在.init.text区段中的顺序无关。
在2.4内核中,这些函数指针的顺序也是和链接的顺序有关的,是不确定的。
__init 宏最常用的地方是驱动模块初始化函数的定义处,其目的是将驱动模块的初始化函数放入名叫.init.text的输入段。当内核启动完毕后,这个段中的内存会被释放掉供其他使用。
__initdata宏用于数据定义,目的是将数据放入名叫.init.data的输入段。其它几个宏也类似。
另外需要注意的是,在以上定意中,用__section__代替了section。还有其它一些类似的宏定义,这里不一一列出,其作用都是类似的。
模块加载分为动态加载和静态加载。
所谓静态加载就是,开机加载系统时将模块加载上去,这就是编译进内核。
而动态加载就是在开机以后将模块加载上去,这就是编译成模块!
init_module是默认的模块的入口,如果你想指定其他的函数作为模块的入口就需要
module_init函数来指定,比如
module_init (your_func);
其中your_func是你编写的一个函数的名称.
init_module()是真正的入口,module_init是宏,如果在模块中使用,最终还是要转换到init_module()上。
如果不是在模块中使用,module_init可以说没有什么作用。总之,使用module_init方便代码在模块和非模块间移植。
以上转自:http://blog.csdn.net/maopig/article/details/7409870
由于4年前对于C语言和Linux的知识贫乏,所以当时对于模块中的函数定义没有细看。这次在温习《LDD3》的时候,重新看了一下关于__init、__initdata和__exit、__exitdata的知识,记录如下:
- PHY: 0:01 - Link is Up - 100/Full
- VFS: Mounted root (nfs filesystem) on device 0:14.
- devtmpfs: mounted
- Freeing init memory: 196K
- INIT: version 2.86 booting
- __init宏使内建模块中的init函数在执行完成后释放掉,不过可装载的模块不受影响。