Init进程

来源:互联网 发布:ubuntu空闲分区不可用 编辑:程序博客网 时间:2024/06/05 17:29

李峰

原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

linux启动流程

从计算机上电开始到内核加载:

计算机如何启动
计算机如何启动1

从内核加载到用户登录如下图,

init(为英语:initialization的简写)是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。
——— [维基百科]
Upstart是一个基于事件的初始化守护进程,用于替代传统的init(多种类Unix计算机操作系统启动时用于执行任务的程序)。——— [维基百科]

Linux启动流程
Linux启动流程2

init进程是什么

init进程是一个普通的用户态进程,特别之处在于它是所有进程的祖宗。它是内核初始化和用户态初始化的结合点,在内核初始化的结尾部分,init进程被启动,然后开始用户态的初始化。

init进程受什么控制

init进程运行完全受/etc/inittab的控制,如果你要追踪内核的初始化,则从init/main.c文件中的start_kernel()函数开始,如果你要追踪用户态的初始化,则要从/etc/rc.d/rc.sysinit脚本开始。

init进程怎么启动的

init进程是内核启动的第一个用户态进程,而start_kernel()是内核汇编和c语言的连接点,在该函数之前,汇编代码会完成一些初始化,比如为c语言准备运行环境,此函数就像c程序的main函数一样。
init/main.c中,start_kernel()是内核的入口,在该函数的最后一行,执行了rest_init();,这个函数里通过函数kernel_thread(kernel_init, NULL, CLONE_FS);创建了一个内核线程,该线程会运行static int __ref kernel_init(void *unused)函数,在该函数的结尾处,有如下代码:

if (!try_to_run_init_process("/sbin/init") ||    !try_to_run_init_process("/etc/init") ||    !try_to_run_init_process("/bin/init") ||    !try_to_run_init_process("/bin/sh"))    return 0;

这段代码即创建了init process,首先运行/sbin/init,如果失败则运行/etc/init,如果又失败则运行/bin/init,然后是/bin/sh,该函数运行完成以后,init process就被创建,预示着内核初始化结束,用户态初始化开始。

start_kernel函数
start_kernel函数3

kernel_thread如何创建内核线程的呢?

kernel_thread函数如下:

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags){    return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,        (unsigned long)arg, NULL, NULL);}

第一个参数即kernel_init函数的地址,为此进程执行时需要执行的函数,此函数返回值为int型,参数是一个void 指针,穿进去的第二个参数是此函数的参数,这里实际值设置为NULL, 第三个参数是创建新进程的标志位,在内核中有定义,这里实际取CLONE_FS ,宏定义如下:#define CLONE_FS 0x00000200 /* set if fs info shared between processes */。此函数返回pid_t变量,即新创建的进程的进程号。
函数内部调用了do_fork函数,函数分析见:do_fork分析,下面分析此函数的关键代码:

p = copy_process(clone_flags, stack_start, stack_size,             child_tidptr, NULL, trace);

copy_process函数创建一个和原来进程一摸一样的进程,复制了原来进程用到的寄存器,和相应的进程环境。然后返回struct task_struct指针,即进程描述符,函数分析见窥探 kernel — copy_process。

kernel_thread()
kernel_thread()函数

进程的切换机制

进程切换统一发生在schedule(void)函数中,核心函数是__schedule(void),函数分析见 schedule()函数篇。


  1. 参见:http://www.ruanyifeng.com/blog/2013/02/booting.html ↩
  2. 参见:http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html ↩
  3. 参见:http://wiki.deepin.org/?title=%E7%B3%BB%E7%BB%9F%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B ↩
0 0
原创粉丝点击