本文转载自:http://www.ibm.com/developerworks/cn/linux/1407_liuming_init1/index.html
(本人学习使用添加了个人成分)
近年来,Linux 系统的 init 进程经历了两次重大的演进,传统的 sysvinit 已经淡出历史舞台,新的 init 系统 UpStart 和 systemd 各有特点,而越来越多的 Linux 发行版采纳了 systemd。本文简要介绍了这三种 init 系统的使用和原理,每个 Linux 系统管理员和系统软件开发者都应该了解它们,以便更好地管理系统和开发应用。本文是系列的第一部分,主要讲述 sysvinit 的特点和使用。
什么是 Init 系统,init 系统的历史和现状
Linux 操作系统的启动首先从 BIOS 【BIOS是英文"Basic Input Output System"的缩略词,直译过来后中文名称就是"基本输入输出系统"。其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。】开始,接下来进入 boot loader【Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。通常,Boot Loader 是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的 Boot Loader 几乎是不可能的。尽管如此,我们仍然可以对 Boot Loader 归纳出一些通用的概念来,以指导用户特定的 Boot Loader 设计与实现。】,由 bootloader 载入内核,进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程。这个进程是系统的第一个进程。它负责产生其他所有用户进程。
init 以守护进程方式存在,是所有其他进程的祖先。init 进程非常独特,能够完成其他进程无法完成的任务。
Init 系统能够定义、管理和控制 init 进程的行为。它负责组织和运行许多独立的或相关的始化工作(因此被称为 init 系统),从而让计算机系统进入某种用户预订的运行模式。
仅仅将内核运行起来是毫无实际用途的,必须由 init 系统将系统代入可操作状态。比如启动外壳 shell 后,便有了人机交互,这样就可以让计算机执行一些预订程序完成有实际意义的任务。或者启动 X 图形系统以便提供更佳的人机界面,更加高效的完成任务。这里,字符界面的 shell 或者 X 系统都是一种预设的运行模式。
大多数 Linux 发行版的 init 系统是和 System V 【System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支。它最初由 AT&T 开发,在1983年第一次发布。一共发行了4个 System V 的主要版本:版本1、2、3 和 4。System V Release 4,或者称为SVR4,是最成功的版本,成为一些UNIX共同特性的源头,例如 ”SysV 初始化脚本“ (/etc/init.d),用来控制系统启动和关闭,System V Interface Definition (SVID) 是一个System V 如何工作的标准定义。】相兼容的,被称为 sysvinit。这是人们最熟悉的 init 系统。一些发行版如 Slackware 采用的是 BSD 风格 Init 系统,这种风格使用较少,本文不再涉及。其他的发行版如 Gentoo 是自己定制的。Ubuntu 和 RHEL 采用 upstart 替代了传统的 sysvinit。而 Fedora 从版本 15 开始使用了一个被称为 systemd 的新 init 系统。
可以看到不同的发行版采用了不同的 init 实现,本系列文章就是打算讲述三个主要的 Init 系统:sysvinit,UpStart 和 systemd。了解它们各自的设计特点,并简要介绍它们的使用。
在 Linux 主要应用于服务器和 PC 机的时代,SysVinit 运行非常良好,概念简单清晰。它主要依赖于 Shell 脚本,这就决定了它的最大弱点:启动太慢。在很少重新启动的 Server 上,这个缺点并不重要。而当 Linux 被应用到移动终端设备的时候,启动慢就成了一个大问题。为了更快地启动,人们开始改进 sysvinit,先后出现了 upstart 和 systemd 这两个主要的新一代 init 系统。Upstart 已经开发了 8 年多,在不少系统中已经替换 sysvinit。Systemd 出现较晚,但发展更快,大有取代 upstart 的趋势。
本文的第一部分先简要介绍 sysvinit。
ysvinit 概况
sysvinit 就是 system V 风格的 init 系统,顾名思义,它源于 System V 系列 UNIX。它提供了比 BSD 风格 init 系统更高的灵活性。是已经风行了几十年的 UNIX init 系统,一直被各类 Linux 发行版所采用。
运行级别
Sysvinit 用术语 runlevel 来定义"预订的运行模式"。Sysvinit 检查 ‘/etc/inittab‘ 文件中是否含有 ‘initdefault‘ 项。 这告诉 init 系统是否有一个默认运行模式。如果没有默认的运行模式,那么用户将进入系统控制台,手动决定进入何种运行模式。
sysvinit 中运行模式描述了系统各种预订的运行模式。通常会有 8 种运行模式,即运行模式 0 到 6 和 S 或者 s。
每种 Linux 发行版对运行模式的定义都不太一样。但 0,1,6 却得到了大家的一致赞同:
- 0 关机
- 1 单用户模式
- 6 重启
通常在 /etc/inittab 文件中定义了各种运行模式的工作范围。比如 RedHat 定义了 runlevel 3 和 5。运行模式 3 将系统初始化为字符界面的 shell 模式;运行模式 5 将系统初始化为 GUI 模式。无论是命令行界面还是 GUI,运行模式 3 和 5 相对于其他运行模式而言都是完整的正式的运行状态,计算机可以完成用户需要的任务。而模式 1,S 等往往用于系统故障之后的排错和恢复。
很显然,这些不同的运行模式下系统需要初始化运行的进程和需要进行的初始化准备都是不同的。比如运行模式 3 不需要启动 X 系统。用户只需要指定需要进入哪种模式,sysvinit 将负责执行所有该模式所必须的初始化工作。
sysvinit 运行顺序
Sysvinit 巧妙地用脚本,文件命名规则和软链接来实现不同的 runlevel。首先,sysvinit 需要读取/etc/inittab 文件。分析这个文件的内容,它获得以下一些配置信息:
- 系统需要进入的 runlevel
- 捕获组合键的定义
- 定义电源 fail/restore 脚本
- 启动 getty 和虚拟控制台
得到配置信息后,sysvinit 顺序地执行以下这些步骤,从而将系统初始化为预订的 runlevel X。
- /etc/rc.d/rc.sysinit
- /etc/rc.d/rc 和/etc/rc.d/rcX.d/ (X 代表运行级别 0-6)
- /etc/rc.d/rc.local
- X Display Manager(如果需要的话)
首先,运行 rc.sysinit 以便执行一些重要的系统初始化任务。在 RedHat 公司的 RHEL5 中(RHEL6 已经使用 upstart 了),rc.sysinit 主要完成以下这些工作。
- 激活 udev 和 selinux
- 设置定义在/etc/sysctl.conf 中的内核参数
- 设置系统时钟
- 加载 keymaps
- 使能交换分区
- 设置主机名(hostname)
- 根分区检查和 remount
- 激活 RAID 和 LVM 设备
- 开启磁盘配额
- 检查并挂载所有文件系统
- 清除过期的 locks 和 PID 文件
完成了以上这些工作之后,sysvinit 开始运行/etc/rc.d/rc 脚本。根据不同的 runlevel,rc 脚本将打开对应该 runlevel 的 rcX.d 目录(X 就是 runlevel),找到并运行存放在该目录下的所有启动脚本。每个 runlevel X 都有一个这样的目录,目录名为/etc/rc.d/rcX.d。
在这些目录下存放着很多不同的脚本。文件名以 S 开头的脚本就是启动时应该运行的脚本,S 后面跟的数字定义了这些脚本的执行顺序。在/etc/rc.d/rcX.d 目录下的脚本其实都是一些软链接文件,真实的脚本文件存放在/etc/init.d 目录下。如下所示: