首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

定制和监视 Linux 系统启动 (1)

定制和监视 Linux 系统启动 (1)

Linux 系统启动过程概述              您可以将 Linux 系统启动过程(从启动电源到让系统完全运行)看作两个概念性阶段:      
  •           从设备引导,加载并初始化 Linux 内核
  •           启动用户空间应用程序(包括服务器进程),挂载另外的文件系统,执行另外的内核配置与定制项,并提供对额外设备的访问权限
        第一阶段中的基本步骤已经在名为 “深入理解 Linux 的启动过程” 的 developerWorks 文章(参见)中讲述过了。这些步骤多年来变化不大,包括使用 GRand Unified Bootloader 2 (GRUB 2),初始 RAM 磁盘的格式与使用方式的不同,以及对第一个启动的用户空间进程(通常是 init 进程)的改变。此阶段中的性能提升主要来自于硬件升级,比如速度更快的启动设备、更快的设备访问机制,以及速度更快的、更加强大的处理器。然而,第二阶段中的性能提升几乎完全是软件端的性能提升,可以继续使用大量不同的方法。      
        缩短阶段 2 系统启动时间有一种简便方法,即提高完成 Linux 启动过程第二阶段的机制性能。然而,改变启动次序本身就可以带来大幅性能提升。缩短阶段 2 系统启动时间的关键方面如下所示:          
  • 最小化:只启动最少的必要服务集合
  • 线性:找出一个服务需要的其他一个或多个服务(也称为依赖性分析),并将这些需要的服务纳入启动过程
  • 平行:尽可能地同时启动独立服务(或相关服务链)
                纵观其历史,Linux 曾使用过各种各样的启动和关闭机制,尽力平衡线性与平行的问题,同时不会完全向后兼容性。下一节讨论了最常用的一些机制,以及如何在系统上监控它们的行为与性能,从而找出可以优化的地方。          
        了解和使用 SysVinit                      Linux 系统上使用的传统系统启动与关闭机制叫作 SysVinit。顾名思义,SysVinit 机制的概念源自于 UNIX® 的 Sys V 版本,它的更恰当的名称应该是 UNIX System V,版本 4 (SVR4),发布于 1989 年。SysVinit init 程序将会读取 /etc/inittab 文件识别出系统到达默认状态(称为系统的默认运行级别)时可用的服务集合,以及为了到达该状态而应该执行的命令。使用 SysVinit 的系统通过 /etc/inittab 文件中的内容项定义这些信息,如  中所示。      
清单 1.           /etc/inittab 中传统的启动相关命令        
1
2
3
si::sysinit:/etc/init.d/rcS
id:5:initdefault:
l5:5:wait:/etc/init.d/rc 5




        第一行确定初始化系统时系统应该执行的第一个脚本。第二行确定系统初始化后的默认运行级别。在这个例子中,默认的运行级别是 5,这通常意味着系统具有完整的网络与图形功能。第三行确定系统为了到达运行级别 5 而应该执行的命令。      
              在使用 SysVinit 时,/etc/init.d 目录包含用于启动和停止所有系统级进程的 shell 脚本。每种运行级别都有自己的目录,其中包含符号链接指向进入或离开相关运行级别时,应该启动或停止的、在 /etc/init.d 目录中选中的 shell 脚本。清单 1 中的第三行告诉 SysVinit 机制执行运行级别 5 相关目录中的脚本,根据您所运行的 Linux 版本,脚本通常为 /etc/rc5.d、/etc/init.d/rc5.d 或 /etc/rc.d/rc5.d。      
        运行级别目录中的符号链接以 S 或 K 字母开头,这表示它应该是在系统进入指定的运行级别时启动(S)相关系统进程,还是应该在系统离开该运行级别时终止(K)它。位于 S 或 K 之后的整数值定义了进入或离开运行级别时应该执行这些脚本的顺序。      
        在 /etc/init.d 目录中添加新脚本时,位于每个脚本开始部分的特定格式的注释会说明该脚本所依赖的其他所有脚本,同时说明与该脚本有关联的运行级别。这些脚本中应该出现的注释和其他信息被定义为 Linux Standard        Base (LSB) 规范的组成部分,该规范由多个 Linux 发行方共同开发,以确保 SysVinit 脚本在不同 Linux 版本上的兼容性。 摘自 init 脚本中注释的 LSB 讨论,它给出了一个这样的例子。      
清单 2.           传统 SysVinit 脚本中的注释块        
1
2
3
4
5
6
7
8
9
10
### BEGIN INIT INFO
# Provides: lsb-ourdb
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start:  2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop OurDB
# Description: OurDB is a very fast and reliable database
# engine used for illustrating init scripts
### END INIT INFO




对每一项的意义进行了说明。
表 1.         SysVinit 脚本的 INIT INFO 区域中的注释      关键字含义Provides            这个初始化脚本提供的服务的逻辑名称。          Required-Start            成功启动此初始化脚本中定义的服务而必须运行的任何其他服务的逻辑名称。          Required-Stop            成功停止此初始化脚本中定义的服务而必须运行的任何其他服务的逻辑名称。          Default-Start            为了启动此初始化脚本定义的服务,执行该初始化脚本所需的运行级别。          Default-Stop            为了停止此初始化脚本定义的服务,执行该初始化脚本所需的运行级别。          Short-Description 与 Description            为了给与初始化脚本中命令相关联的服务提供简要说明。很多查询和概括 SysVinit 初始化脚本的系统实用工具都使用了这些关键字。         
        您可以使用 /sbin/service 命令来启动、停止与列出 SysVinit 脚本,也可以使用 /sbin/chkconfig 命令来列出或修改与脚本有关联的运行级别。      
        使用 shell 脚本启动系统可以很方便地给系统的启动过程增加新命令,或者修改启动或停止某项服务时发生的操作。也可以轻松在引导次序中的某个特定点增加新服务,只要创建到新服务的符号链接并在符号链接的名称中使用正确编号即可。      
        从性能的角度讲,SysVinit 按照指定的顺序执行多个 shell 脚本,从而到达指定的运行级别。执行 shell 脚本相对较慢,此外,因为无法利用可能的并行机制,这样的顺序启动机制原本需要的时间就很长。与目标运行级别相关联的每个 shell 脚本必须按顺序执行,而这种顺序是通过指向每个 shell 脚本的符号链接名称中的编号来指定的,其他服务只能等到当前服务完成后才能启动。因此,使用  SysVinit 的系统可以集成本文上一节()中讨论的启动监控与配置工具,从而确定每个启动脚本所花费的具体时长。          
        关于 SysVinit 机制更加详细的讨论,请参见 developerWorks 文章 “更快启动 Linux”(参见)。      
        了解和使用事件驱动的启动机制              尽管 SysVinit 易于使用和修改,因为它使用了 shell 脚本来启动与停止系统服务,但使用有序的 shell 脚本会让 SysVinit 变慢,并且不能并行启动不相关的服务。另一个问题是,启动与停止服务的脚本只在系统启动或关闭时才能执行,换句话说,系统运行级别的改变是它们惟一会响应的事件。很少有例外(比如由其他服务启动的服务),这意味着系统需要的所有服务必须一直运行,等待着可能永远不会来的请求。      
        无论从内存与处理器资源消耗方面,还是从首先启动它们所需的事件方面考虑,运行不使用的进程都是低效的。当今日益灵活的系统需要能够在各种环境中正确地、无缝地工作,比如网络连接从有线变为无线,从一个网络迁移到另一个网络,或者诸如增加和移除存储设备与其他外围设备这样的硬件变化。      
        事件驱动的机制正如其名所示,在系统发生特定事件时执行特定命令并启动相关服务。用于各种网络服务的 inetd 与 xinetd 守护进程对事件驱动的启动机制进行了很好地模拟,因为它们会等待某些事件发生(对它们所管理服务的网络连接请求),然后根据需要启动正确的服务。事件驱动的启动机制支持在响应事件时同时执行多个命令,并将同样的动态响应扩展到系统的运行时环境,从而最大程度地提高系统启动期间的并行化程度。事件实质上就是进程发送的字符串消息,用户可使用该消息作为对进程所监控状态出现变化的响应。一个进程发送一个事件消息。      
        最知名的事件驱动启动机制是 Upstart,它是很多 Linux 发行上使用的默认启动机制,包括 Ubuntu 9.10 及以上版本、RHEL6 及相关发行如 CentOS、Oracle Linux、Scientific Linux、Fedora 9-14 和其他众多 Linux 发行版本。Upstart 提供与 SysVinit 运行级别模型的向后兼容。      
        Upstart 使用任务配置(或 conf)文件来识别对事件的响应,比如启动、关闭、运行级别(运行级别变化)等。这些文件通常位于 /etc/init 目录中,但有些因为历史原因转移到了 /etc/event.d 目录中。您创建的任意新的系统级 conf 文件都应该位于 ./etc/init 目录中。Conf 文件的扩展名通常为 .conf。它们是文本文件,而且至少必须包含以下内容:      
  •           为了响应一个或多个事件,conf 文件应该执行某些操作。例如,start on startup 项说明在收到 startup 事件时应该执行一个任务文件,而 stop on runlevel 项说明在收到 runlevel 事件时应该停止一个任务文件,比如系统的运行级别改变时。
  • task 或 respawn 部分至少包含一个 exec 项,而 script 部分指定了响应触发此任务文件的事件时执行的命令。exec 项用于执行一个带有一组特定命令行参数的特定命令,通常为二进制命令。script 部分又叫作            stanza,它提供 shell 执行的命令,和其他 shell 脚本一样必须以 end script 语句结尾。Upstart            通过 task 和 respawn 关键字管理任务的两个概念性类:         
    •               任务必须完成,这意味着它们必须从停止状态转变为启动状态,然后在完成之后返回到停止状态。
    •               服务必须始终运行,因此只要从停止状态转变为启动状态。respawn 部分说明了如何启动和重启一项服务。
              您还可以在 Upstart conf 文件的 task 部分使用其他关键字来识别输出设备,在执行主要的 exec 或 script 部分之前运行脚本,在完成主要的 exec 或 script 部分之后运行脚本,诸如此类。pre-start script 部分提供了一些命令来初始化 script 或 exec 命令所需的环境,而 post-stop script 部分则提供了一些命令,在 exec 命令或 script stanza 完成后进行清理或执行后处理。任务文件中还有其他许多可用的 Upstart 命令(请参见)。      
              例如, 是一个 /etc/init/rcS.conf Upstart 任务文件,它模拟了 SysVinit 机制。它通过删除注释来提高代码可读性。      
清单 3.           /etc/init/rcS.conf Upstart 任务文件        
1
2
3
4
5
6
7
8
9
start on runlevel [0123456]

stop on runlevel [!$RUNLEVEL]

task

export RUNLEVEL
console output
exec /etc/rc.d/rc $RUNLEVEL




        这个 conf 文件定义了一个任务,从与当前运行级别有关联的目录中运行所有现有的 SysVinit 脚本。      
        可以使用 /sbin/initctl 命令来启动、停止和列出 Upstart 任务。此命令可以显示当前正在运行的 Upstart 任务及其当前状态。在系统的初始化次序中添加一个新任务,只需要为该服务创建一个正确的 conf 文件,并在 /etc/init 目录中安装该文件。Upstart versions 1.3 及其更高版本甚至支持位于用户主目录的 .init 子目录中的用户特定的 conf 文件,但这个选项通常不受支持。
返回列表