我将只讨论 Linux 系统主要使用的 “System V” 风格的 init。还有其他的替代方案。事实上,你可以把你喜欢的任何程序放在 /sbin/init
中,内核会在加载完成后运行它。
init
的工作是使一切都按应有的方式运行。它检查文件系统是否正常并挂载它们。它启动“守护进程”来记录系统消息、进行网络连接、提供网页服务、监听你的鼠标等等。它还启动 getty 进程,这些进程在你的虚拟终端上放置登录提示符。
关于切换“运行级别”有一个非常复杂的故事,但我将主要跳过它,只谈论系统启动。
Init 读取文件 /etc/inittab
,该文件告诉它要做什么。通常,它被告知要做的第一件事是运行一个初始化脚本。执行(或解释)这个脚本的程序是 bash
,与给你命令提示符的程序相同。在 Debian 系统中,初始化脚本是 /etc/init.d/rcS
,在 Red Hat 中,是 /etc/rc.d/rc.sysinit
。在这里文件系统被检查和挂载,时钟被设置,交换空间被启用,主机名被设置等等。
接下来,另一个脚本被调用,将我们带入默认的运行级别。这仅仅意味着一组要启动的子系统。在 Red Hat 中有一组目录 /etc/rc.d/rc0.d
、/etc/rc.d/rc1.d
、...、/etc/rc.d/rc6.d
,或者在 Debian 中有 /etc/rc0.d
、/etc/rc1.d
、...、/etc/rc6.d
,它们对应于运行级别。如果我们要进入 Debian 系统上的运行级别 3,那么该脚本会运行 /etc/rc3.d
中所有以 `S'(表示启动)开头的脚本。这些脚本实际上只是指向另一个通常名为 init.d
的目录中的脚本的链接。
因此我们的运行级别脚本被 init
调用,它正在一个目录中查找以 `S' 开头的脚本。它可能首先找到 S10syslog
。这些数字告诉运行级别脚本以什么顺序运行它们。所以在这种情况下,S10syslog
首先运行,因为没有以 S00 ... S09 开头的脚本。但是 S10syslog
实际上是指向 /etc/init.d/syslog
的链接,这是一个启动和停止系统日志记录器的脚本。因为链接以 `S' 开头,所以运行级别脚本知道用 “start” 参数执行 syslog
脚本。还有以 `K'(表示 kill)开头的相应链接,它们指定在离开运行级别时要关闭什么以及以什么顺序关闭。
要更改默认启动的子系统,你必须在 rcN.d
目录中设置这些链接,其中 N 是在你的 inittab
中设置的默认运行级别。
init 做的最后一个重要的事情是启动一些 getty
进程。这些进程是“重生的”,这意味着如果它们停止,init
会再次启动它们。大多数发行版都带有六个虚拟终端。你可能想要更少以节省内存,或者更多,这样你就可以让很多东西运行,并在需要时快速切换到它们。你也可能想要为一个文本终端或拨号调制解调器运行一个 getty
进程。在这种情况下,你需要编辑 inittab
文件。
/etc/inittab
是 init 的顶级配置文件。
rcN.d
目录,其中 N = 0, 1, ..., 6 决定了哪些子系统被启动。
在 init 调用的某个脚本中,将发出 mount -a
命令。这意味着挂载所有应该被挂载的文件系统。文件 /etc/fstab
定义了应该挂载什么。如果你想更改系统启动时挂载的内容和位置,你需要编辑这个文件。有一个关于 fstab
的 man 手册。
找到你的系统默认运行级别的 rcN.d
目录,并执行 ls -l
来查看这些文件链接到哪里。
更改你的系统上运行的 getty 进程的数量。
从你的默认运行级别中移除任何你不需要的子系统。
看看你可以用多小的配置来启动系统。
设置一个软盘,包含 lilo、一个内核和一个名为 /sbin/init
的静态链接的 “hello world” 程序,并观察它启动并输出 hello。
仔细观察你的系统启动,并记录它告诉你正在发生的事情。或者打印你的系统日志 /var/log/messages
中启动时间的部分。然后从 inittab
开始,浏览所有脚本,看看哪些代码做了什么。你也可以放入额外的启动消息,例如
echo "Hello, I am rc.sysinit"
这也是学习 Bash shell 脚本的好练习,其中一些脚本相当复杂。手边准备一份好的 Bash 参考手册。
inittab
和 fstab
文件的 man 手册。在 shell 中输入(例如)man inittab
来查看它。