init
init(为英語:initialization的简写)是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。Linux系統在開機時載入Linux內核後,便由Linux內核載入init程式,由init程式完成餘下的開機過程,比如載入執行級別,載入服務,啟動Shell/圖形化界面等等。
Unix 系列中(如 System III 和 System V)init的作用,和研究中的 Unix 和 BSD 衍生版本相比,发生了一些变化。大多数Linux发行版是和 System V 相兼容的,但是一些发行版如Slackware 采用的是BSD风格,其它的如 Gentoo 是自己定制的。後來Ubuntu[1][2] 和其他一些發行版採用 Upstart[3] 來代替[4] 傳統的 init 處理程序。至2015年,大部分Linux發行版都已採用新的systemd替代System V和Upstart,但systemd向下相容System V。
BSD风格
BSD init 运行存放于'/etc/rc'的初始化 shell 脚本,然后启动基于文本模式的终端(getty)或者基于图形界面的终端(窗口系统,如 X)。 这里没有运行模式的问题,因为文件 'rc' 决定了 init 如何执行。
优点: 简单且易于手动编辑。
缺点: 如果第三方软件需要在启动过程执行它自身的初始化脚本,它必须修改已经存在的启动脚本,一旦这种过程中有一个小错误,都将导致系统无法正常启动。
值得注意的是,现代的 BSD 衍生系统一直支持使用 'rc.local' 文件的方式,它将在正常启动过程接近最后的时间以子脚本的方式来执行。这样做减少了整个系统无法启动的风险。然后,第三方软件包可以将它们独立的 start/stop 脚本安装到一个本地的 'rc.d' 目录中(通常这是由 ports collection/pkgsrc 完成的)。 FreeBSD 和 NetBSD 现在默认使用 rc.d ,该目录中所有的用户启动脚本,都被分成更小的子脚本,和 SysV 类似。rcorder 通常根据在 rc.d目录中脚本之间的依赖关系来决定脚本的执行顺序。
SysV风格
System V init检查 '/etc/inittab' 文件中是否含有 'initdefault' 项。这告诉init系统是否有一个默认运行模式。如果没有默认的运行模式,那么用户将进入系统控制台,手动决定进入何种运行模式。
运行模式
System V中运行模式描述了系统各种可能的状态。通常会有 8 种运行模式,即运行模式0到6和S或者s。其中运行模式3为"保留的"运行模式:
- 0.关机
- 1.单用户模式
- 6.重启
除了模式0,1,6外,每种Unix和Unix-like系统对运行模式的定义不太一样。通常在 /etc/inittab文件中定义了各种运行模式的工作范围。
目前絕大多數Linux發行版已經基於新的systemd,systemd一般不再使用/etc/inittab檔案,也使用新的target取代System V的執行等級,但仍然相容System V的執行等級。若要設定系統預設的執行模式,需要使用systemctl default targetname.target命令。
默认的运行模式
操作系统 | 默认的运行模式 |
---|---|
AIX | 2 |
Arch Linux | 3 |
CentOS | 3 |
Debian GNU/Linux | 2 [5] |
Gentoo Linux | 3 |
Mandriva Linux | 5 |
Mac OS X | 3 |
Red Hat Linux / Fedora | 3 or 5 |
Slackware Linux | 3 |
Solaris | 3 [6] |
SUSE Linux | 5 [7] |
Ubuntu | 2 [8] |
上面的表中有两种Linux发行版默认的运行模式为5,模式5是多用户图形环境(X Window System),通常还包括X显示管理器。然而在Solaris操作系统中,模式5被保留用来执行关机和自动切断电源。
大多数操作系统的用户可以用下面的命令来判断当前的运行模式是什么:
$ runlevel
$ who -r
在 root 权限下,运行 telinit 或者 init 命令可以改变当前的运行模式。 /etc/inittab 文件中设置的默认的运行模式在 :initdefault: 项中。
跳过 init
Linux系统中,现代的bootloader(如LILO或者GRUB),用户可以在初始化过程中最后启动的进程来取代默认的 /sbin/init
。
通常是在bootloader环境中通过执行 init=/foo/bar
命令。例如,如果执行 init=/bin/bash
,启动单用户root的shell环境,无需用户密码。
BSD的变种,大多数平台,bootstrap程序是可以被打断的,然后执行boot -s
命令进入单用户模式。
单用户模式并不没有跳过init,它仍然可以执行 /sbin/init
,但是它将使init询问exec()
将要执行的命令 (默认为 /bin/sh
) 的路径,而不是采用正常的多用户启动顺序。如果内核启动时在 /etc/ttys
文件中被标注为"不安全"(在某些系统中,当前的"安全模式"可能会有些变化),在允许这种情况(或者回退到单用户模式,如果用户执行 CTRL+D
),init将首先询问root用户的密码。
如果该程序退出,内核将在多用户模式下重新执行 init。如果系统从多用户模式切换到单用户模式,还将碰到上述的情况。
如果内核加载后,init不能被正常启动,这将导致 panic 错误,此时系统将不可使用。想要通过init自身来改变init的路径,不同的版本情况不太一样(NetBSD中可执行boot -a
;FreeBSD中利用init_path
命令装载变量)。
其他风格
很多人一直努力地从某些方面改进传统的 init 守护进程,使它变得更完善。下面列出的是一些改进(排序不分先后):
- SystemStarter:用来替代 launchd — Apple Mac OS X开启进程
- Initng:完全代替 init ,可以异步开启进程
- Upstart:完全代替 init ,可以异步开启进程,曾由Ubuntu等使用
- Service Management Facility:完全代替/重新设计 Solaris 启动 Solaris 10
- runit:跨平台的完全代替 init 可以并行启动服务
- BootScripts:GoboLinux
- Mudur:用 Python 写成的 init 替代品, 可以异步开启进程,Pardus Linux 发行版
- systemd:完全替代init,可并行启动服务,并能减少在shell上的系统开销,相比传统的System V是一大革新,已被大多数Linux发行版所使用
下面列出的项目还没有大范围的使用:
- eINIT, 完全代替 init ,可以异步开启进程,但是完成这个过程可以不使用 shell 脚本
- svscan 来自 daemontools 被用作 1 号进程 - 似乎将被 runit 替代
- cinit
- twsinit, 部分用 x86 汇编写成, 只是用来证明一种概念
- minit
- OpenRC,由Gentoo客制
参考文献
- ^ 存档副本. [2009-06-09]. (原始内容存档于2016-03-06).
- ^ 存档副本. [2009-06-09]. (原始内容存档于2009-06-02).
- ^ 存档副本. [2009-09-12]. (原始内容存档于2009-09-04).
- ^ 存档副本. [2009-06-09]. (原始内容存档于2017-03-14).
- ^ 存档副本. [2009-06-09]. (原始内容存档于2021-02-01).
- ^ 存档副本. [2011-06-13]. (原始内容存档于2007-08-18).
- ^ 存档副本 (PDF). [2009-06-09]. (原始内容 (PDF)存档于2006-11-04).
- ^ 存档副本. [2009-06-09]. (原始内容存档于2021-02-01).
外部链接
- Linux init man page
- FreeBSD init man page (页面存档备份,存于互联网档案馆)
- boot-scripts
- runit (页面存档备份,存于互联网档案馆)
- minit (页面存档备份,存于互联网档案馆)
- rc.d (页面存档备份,存于互联网档案馆)
- busybox(页面存档备份,存于互联网档案馆)
- smf and milestones in Solaris 10(页面存档备份,存于互联网档案馆)
- cinit
- twsinit (页面存档备份,存于互联网档案馆)
- Mudur
参见
- pidof 或者 killall5, 从 System V 开始在很多发行版中使用的另一种程序