您的位置:首页 > 其它

分析kernel的initial函数

2011-06-16 16:09 190 查看


分析kernel的initcall函数

分析
kernel

initcall
函数

Author: Dongas

Data: 08-07-15

先来看看这些
initcall
函数的声明:

/* include/linux/init.h */

/* initcalls are now grouped by functionality into separate

* subsections. Ordering inside the subsections is determined

* by link order.

* For backwards compatibility, initcall() puts the call in

* the device init subsection.

*/

#define __define_initcall(level,fn) /

static initcall_t __initcall_##fn __attribute_used__ /

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

#define core_initcall(fn)
__define_initcall("1",fn)

#define postcore_initcall(fn)
__define_initcall("2",fn)

#define arch_initcall(fn)
__define_initcall("3",fn)

#define subsys_initcall(fn)
__define_initcall("4",fn)

#define fs_initcall(fn)
__define_initcall("5",fn)

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

#define late_initcall(fn)
__define_initcall("7",fn)

#define __initcall(fn) device_initcall(fn)

#define __exitcall(fn) /

static exitcall_t __exitcall_##fn __exit_call = fn

#define console_initcall(fn) /

static initcall_t __initcall_##fn /

__attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn

#define security_initcall(fn) /

static initcall_t __initcall_##fn /

__attribute_used__ __attribute__((__section__(".security_initcall.init"))) = fn

#define module_init(x)
__initcall(x);

ß

从这里知道
module_init
的等级为
6
,相对靠后

#define module_exit(x)
__exitcall(x);

可以发现这些
*_initcall(fn)
最终都是通过
__define_initcall(level,fn)
宏定义生成的。

__define_initcall
宏定义如下:

#define __define_initcall(level,fn) /

static initcall_t __initcall_##fn __attribute_used__ /

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

这句话的意思为定义一个
initcall_t
型的初始化函数,函数存放在
.initcall”level”.init section
内。
.initcall”level”.init section
定义在
vmlinux.lds
内。

/* arch/arm/kernel/vmlinux.lds */

……

__initcall_start = .;

*(.initcall1.init)

*(.initcall2.init)

*(.initcall3.init)

*(.initcall4.init)

*(.initcall5.init)

*(.initcall6.init)

*(.initcall7.init)

__initcall_end = .;

……

正好包括了上面
init.h
里定义的从
core_initcall

late_initcall

7

level
等级的
.initcall”level”.init section.
因此通过不同的
*_initcall
声明的函数指针最终都会存放不同
level
等级的
.initcall”level”.init section
内。这些不同
level

section

level
等级高低依次存放。

下面我们再来看看,内核是什么时候调用存储在
.initcall”level”.init section
内的函数的。

内核是通过
do_initcalls
函数循环调用执行
initcall.init section
内的函数的,流程如下:

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

这里要分析两个函数
: kernel_thread

do_initcalls
,这两个函数都定义在
init/main.c


1)
kernel_thread



1.static void noinline rest_init(void)

2.
__releases(kernel_lock)

3.{

4.
system_state = SYSTEM_BOOTING_SCHEDULER_OK;

5.

6.
kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);

7.
numa_default_policy();

8.
unlock_kernel();

9.

10.
/*

11.
* The boot idle thread must execute schedule()

12.
* at least one to get things moving:

13.
*/

14.
__preempt_enable_no_resched();

15.
schedule();

16.
preempt_disable();

17.

18.
/* Call into cpu_idle with preempt disabled */

19.
cpu_idle();

20.}


6
行通过
kernel_thread
创建一个内核线程执行
init
函数。(其实这里创建的即

Linux
的1号进程
(init
进程
),

linux
中所有其他进程的父进程,有兴趣的可以自己查资料)

2)
do_initcalls



1.static void __init do_initcalls(void)

2.{

3.
initcall_t *call;

4.
int count = preempt_count();

5.

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

7.
……

8.
result = (*call)();

9.
……

10.
}

11.}

其中
, initcall_t
类型如下:

typedef int (*initcall_t)(void);

__initcall_start

__initcall_end
定义在
vmlinux.lds
内,表示
initcall section
的起始和结束地址。

/* arch/arm/kernel/vmlinux.lds */

……

__initcall_start = .;

*(.initcall1.init)

*(.initcall2.init)

*(.initcall3.init)

*(.initcall4.init)

*(.initcall5.init)

*(.initcall6.init)

*(.initcall7.init)

__initcall_end = .;

……

因此,上面
6-10
行代码的作用为按
initcall level
等级的顺序,依次循环调用预先存储在
initcall section
内的所有各个级别的初始化函数。这样,
kernel

initcall
函数的原理我们就搞清楚了。

最后要注意的是
rest_init
是在
start_kernel
函数内最后部分才被调用执行的,
rest_init
前包含了
kernel
一系列的初始化工作。另外,这些不同
level
等级的
initcall.init section
本身有一定的执行顺序,因此如果你的驱动依赖于特定的执行顺序的话需要考虑到这一点。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: