init进程相关

来源:互联网 发布:sql不同数据类型运算 编辑:程序博客网 时间:2024/06/08 02:12

init进程的建立

Linux将要建立的第一个进程是init进程,建立该进程是以调用kernel_thread(init ,NULL,0)这个函数的形式进行的。init进程是很特殊的——它是Linux的第一个进程,也是其它所有进程的父进程。让我们来看一下它是怎样产生的。

在调用kernel_thread(init,NULL,0)函数时,会调用main.c中的另外一个函数——init()。请注意init()函数和init进程是不同的概念。通过执行inin()函数,系统完成了下述的工作:

·建立dbflush、kswapd两个新的内核线程。

·初始化tty1设备。该设备对应了多个终端(concole),用户登录时,就是登录在这些终端上的。

·启动init进程。Linux首先寻找“/etc/init”文件,如果找不到,就接着找“/bin/init”文件,若仍找不到,再去找“/sbin/init”。如果仍无法找到的话,启动将无法进行下去。否则,便执行init文件,从而建立init进程。

 

当etc/init(假定它存在)执行时,建立好的init进程将根据启动脚本文件的内容创建其它必要的进程去完成一些重要的操作:

(1) 文件系统检查。

(2) 启动系统的守护进程。

(3) 对每个联机终端建立一个“getty”进程。

(4) 执行“/etc/rc”下的命令文件。

 

此后,“getty”会在每个终端上显示“login”提示符,以等待用户的登录。此时“getty”会调用“exec”执行“login”程序,“login”将核对用户帐户和密码,如果密码正确,“login”调用“exec”执行shell的命令行解释程序(当然,也可以执行X-windows,如果用户设置了的话)。shell接着去执行用户默认的系统环境配置脚本文件(通常是用户的home目录下的profile文件)。

init还有另外一个任务,当某个终端或虚拟控制台上的用户注销之后,init 进程要为该终端或虚拟控制台重新启动一个 “getty”,以便能够让其他用户登录。这是为什么呢?你应该发现,当用户登录时,“getty”用的是“exec”而不是“fork”系统调用来执行“login”,这样,“login”在执行的时候会覆盖“getty”的执行环境。(同理,用户注册成功后,“login”的执行环境也会被shell占用)所以,如果想再次使用同一终端,必须再启动一个“getty”。

此外,init 进程还负责管理系统中的“孤儿”进程。如果某个进程创建子进程之后,在子进程终止之前终止,则子进程成为孤儿进程。init 进程负责“收养”该进程,即孤儿进程会立即成为 init进程的子进程。这是为了保持进程树的完整性。

init 进程的变种较多,大多数 Linux 的发行版本采用 sysvinit(由 Miquel van Smoorenburg)。这是一个编译好的软件包。由于 System V 而得名。UNIX 的 BSD 版本有不同的 init,主要区别在于是否具有运行级别(关于运行级别的问题下面会有专门的描述):System V 有运行级别,而 BSD 没有运行级别。但这种区别并不是本质的区别。

图5.12是上述流程的流程图。






系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。整个linux系统的所有进程也是一个树形结构。树根 是系统自动构造的,即在内核态下执行的0号进程,它是所有进程的祖先。由0号进程创建1号进程(内核态),1号负责执行内核的部分初始化工作及进行系统配 置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1号进程调用execve()运行可执行程序init,并演变成用户态1号进程,即 init进程。它按照配置文件/etc/initab的要求,完成系统启动工作,创建编号为1号、2号...的若干终端注册进程getty。

        每个getty进程设置其进程组标识号,并监视配置到系统终端的接口线路。当检测到来自终端的连接信号时,getty进程将通过函数execve()执行 注册程序login,此时用户就可输入注册名和密码进入登录过程,如果成功,由login程序再通过函数execv()执行shell,该shell进程 接收getty进程的pid,取代原来的getty进程。再由shell直接或间接地产生其他进程。

 

  上述过程可描述为:0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程

   注意,上述过程描述中提到:1号内核进程调用执行init并演变成1号用户态进程(init进程),这里前者是init是函数,后者是进程。两者容易混淆,区别如下:

   1.init()函数在内核态运行,是内核代码

   2.init进程是内核启动并运行的第一个用户进程,运行在用户态下。

   3.一号内核进程调用execve()从文件/etc/inittab中加载可执行程序init并执行,这个过程并没有使用调用do_fork(),因此两个进程都是1号进程。


原创粉丝点击