并行启动应用程序从而加速 Linux 的引导
2008-12-01 07:20
323 查看
并行启动应用程序从而加速 Linux 的引导
使用 initng 和 upstart级别: 中级M. Tim Jones (mtj@mtjones.com), 顾问工程师, Emulex
2007 年 3 月 26 日
对
于 Linux® 的最大抱怨(尤其来自开发人员)就是 Linux 的引导速度。默认情况下,Linux
是一个通用的操作系统,可以作为一个开箱即用的客户机桌面或服务器使用。由于 Linux
具有很好的灵活性,因此可以用作各种用途的基础,但对于任何特定的配置来说,尚不是最理想的选择。本文将向您展示可以提高 Linux
引导速度的一些方法,包括两种可以对初始化过程进行并行化操作的方法。本文还介绍了如何图形化地表现引导过程的性能。
对于 GNU/Linux 常见的抱怨之一(除了缺乏良好的内核调试器之外)就是操作系统的启动需要花费大量时间。您可以将这个过程概括为引导,不过实际上已经有几个独立的项目开始从冷系统改进到可以通过 shell 或窗口管理器与系统进行交互。让我们来回顾一下 Linux 的引导和初始化过程。
Linux 引导的主要阶段
尽管引导 Linux 会涉及很多步骤,不过您可以将整个过程划分为 3 个基本步骤,我将它们分别称之为 BIOS、内核引导 和 系统初始化,如图 1 所示。
图 1. Linux 引导过程的短暂视图
BIOS
当第一次启动计算机或重启时,计算机的处理器会在一个众所周知的位置开始执行,即基本输入/输出系统(BIOS)。
BIOS 通常存储在系统主板的一个闪存设备中。BIOS
需要执行很多工作,例如对基本组件(例如系统内存)进行初始测试,确定如何引导操作系统。由于基于 PC
的计算机都非常灵活,因此引导设备可以是连接到主板上的各种设备之一,包括硬盘、CD-ROM 或其他设备,例如网络接口。
通过选择最经常引导的设备(通常是硬盘)可以优化确定引导设备的过程。不过到目前为止,BIOS 阶段最耗时的过程就是内存测试。将这个测试的某些部分禁用(例如内存完全测试)确实有助于加快引导速度,不过这样做的代价是丢失了引导时对系统的完整性测试。
内核引导
找到引导设备后,开始 Linux 内核引导过程。这个过程发生在两个阶段(大约) —— 第一阶段引导 和第二阶段引导。
第一阶段包含了一个简单的引导加载程序(这可以在引导设备的主引导记录 MBR
中找到),其作用是加载第二阶段的引导加载程序。第一阶段的引导加载程序使用分区表来找到第二阶段的引导加载程序。第一阶段的引导加载程序对表进行扫描,
查找活动分区;当加载程序找到分区时,就将第二阶段的引导加载程序加载到 RAM 中并调用它。
在第二阶段的引导加载程序加载到 RAM 中之后,Linux 内核映像和初始 RAM 磁盘映像(
initrd)也会被加载到 RAM 中。当调用内核时,它会自解压到高端内存中,并拷贝
initrd以供稍后安装和使用。
|
init进程。由于
init是 Linux 系统中创建的第一个进程,因此它是所有其他进程的祖先(所有的进程都是
init的后代)。
系统初始化
init进程 —— 本文的重点 —— 是内核引导过程完成时创建的第一个进程。Linux 使用了
init进程来对组成 Linux 的服务和应用程序进行初始化。
当
init进程启动时,它会打开一个名为 /etc/inittab 的文件。这个文件是
init的配置文件,定义了如何对系统进行初始化。这个文件还包含了有关出现电源故障时执行的操作(如果系统支持)、以及在检测到 Ctrl-Alt-Delete 键序列时应该如何反应的信息。请参看 清单 1 中该文件的简短片段,了解它所提供的内容。
inittab配置文件使用通用格式定义了几项内容:id:runlevels:action:process。其中 id 是惟一标识该项的字符序列。runlevels 定义了操作所使用的运行级别。action 指定了要执行的特定操作。最后,process 定义了要执行的进程。
清单 1. inittab 文件摘录
# The default runlevel id:2:initdefault # Boot-time system configuration/initialization script si::sysinit:/etc/init.d/rcS # Runlevels l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 z6:6:respawn:/sbin/sulogin # How to react to ctrl-alt-del ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now |
|
init加载 /etc/inittab 之后,就会将系统切换到
initdefault操作所定义的运行级别。如 清单 1
所示,即运行级别 2。我们可以将运行级别看作是系统的状态。例如,运行级别 0 定义了系统挂起状态,运行级别 1 是单用户模式。运行级别 2 到
5 是多用户状态,运行级别 6
表示重启。(注意有些发行版对于运行级别的表示是不同的)。还可以以另一种方式考虑运行级别,即它是一种定义可以执行哪些进程(定义系统状态的进程)的方
法。
注意: 要查看系统的当前运行级别,请使用命令
runlevel。
正如 清单 1 定义的一样,
initdefault指定默认的
init级别是 2 (多用户模式)。在定义初始的运行级别之后,则调用
rc脚本以及参数
2(运行级别)来启动系统。这个脚本然后会调用各种服务和应用程序脚本来启动或停止特定的元素。在本例中,文件都是在 /etc/rc2.d/ 中定义的。例如,如果要启动 MySQL 应用程序(例如系统启动),可以这样调用:
/etc/rc2.d/S20mysql start。在关闭系统时,则使用
stop参数调用相同的脚本集。
|
关于这个问题的一个很明显的解决方案是去掉
init命令的串行特性,将其替换成并行化操作。在很多多处理系统中都可以看到这种用法。例如,socket striping,或者使用两个或多个 socket 并行地移动数据,就是一个基于这个主题的解决方案。独立磁盘冗余阵列(RAID)系统也是通过将磁盘分成条状(通常是并行的)来提高 I/O 性能。
|
init进程(
sysvinit)是一个串行化的进程,因此可对这部分系统进行充分优化。实际上,您可以使用任何方法来对
init进程进行优化。让我们来了解其中一些方法,以及它们是如何解决这个问题的。前两种方法是基于依赖关系的(即使用依赖关系来提供并行化),第三种方法是一个基于事件的系统(即进程依赖于事件来表示自己何时启动或停止)。
第一种方法
initng(下一代
init)将完全取代异步启动进程的
init,能够更加快速地完成
init进程。在编写本文时,
initng是一个 beta 版本的产品,其创建者是 Jimmy Wennlund。
initng背后的基本思想是只要满足了服务的依赖关系就可启动。这样系统就可以在 CPU 和 I/O 之间实现较好的平衡。当从磁盘上加载一个脚本或等待硬件设备启动的同时,可以运行另一个脚本来启动另外一个服务。
initng 工作原理
作为一个基于依赖关系的解决方案,
initng使用自己的初始化脚本集,它们对服务和守护进程的依赖性进行了编码。清单 2 展示了一个示例。这个脚本指定了需要为给定的运行级别启动的服务。该服务具有两个依赖关系,使用
need关键字定义,分别是 system/initial 和 net/all。在 system/my_service 可以启动之前,这些服务必须是可用的。当这些服务可用时,
exec关键字就开始起作用了。
exec关键字(以及
start选项)定义了如何使用任何可用的选项启动服务。要停止这个服务,就会使用
exec关键字以及
stop选项。
清单 2. 为 initng 定义服务
service system/my_service { need = system/initial net/all; exec start = /sbin/my_service --start --option; exec stop = /sbin/my_service --stop --option; } |
initng看作一个基于目标的系统。其目标就是要启动的服务。没有进行显式的规划;相反,依赖关系简单地定义了服务初始化的流程,这个过程中隐含着并行化的操作。
使用 initng
initng包对于典型用法的安装来说相对简单。对于使用非标准包(不是默认配置中出现的包)来说,必须要进行一些汇编工作。
initng的典型安装需要
initng发行版(源代码或二进制文件)和 ifiles 发行版。您可以使用 ./configure、
make和
make install编译自己的
initng发行版。您必须使用
cmake来编译 ifiles 文件(这是脚本文件)。根据系统需求的不同,您可能需要创建新的服务/守护进程定义(不过很可能
initng社区中已经有人这样做了)。然后您还必须修改 LILO 或 GRUB 的配置以指向新的 /sbin/initng。
要控制
initng,需要使用
ngc(比较
telinit与传统的
init)。它们的语法有些不同,不过功能是相同的。
替换
init的另外一种选择是
upstart,它使用的方法与
initng使用的方法稍有不同。
upstart是一个基于事件的
init的替代程序,这意味着服务的启动和停止都基于事件的通信。
upstart正在由 Scott James Remnant 进行开发,用于 Ubuntu 发行版,不过它想要成为任何 Linux 发行版上
init的通用替代程序。
upstart 的工作原理
Upstart要求您更新初始化脚本来支持基于事件的操作模式。
upstart维护自己的在系统启动时启动的
init进程(对于所有其他方法也是如此)。 首先,
init会发出 startup 事件 —— 这是两个核心事件之一。事件 startup 是由
init在系统启动时发出的,事件 shutdown 则是在系统关闭时发出的。其他核心事件包括 ctrlaltdel,它说明您按下了 Ctrl-Alt-Delete,或 kbdrequest,它用来说明您按下了 Alt-Up(向上箭头)键组合。
您可以为其他用法创建新事件。例如,您可以创建一个名为 myevent 的任意事件,并使用
echo命令表示该事件的接收。请使用下面这个简短的作业:
on myevent exec echo myevent received console output |
upstart配置(/etc/event.d)中给出的文件,可以使用
initctl工具触发它:
initctl emit myevent |
upstart使用的脚本文件的工作方式类似与传统的
rc init文件,它们是基于异步事件自发操作的。清单 3 提供了一个简单的样例脚本,它可以接收 3 个事件: startup,启动作业;shutdown 和 runlevel-3,停止作业。shell 执行作业的
script部分的内容(使用
-e选项来结束出错脚本)。
清单 3. sysvinit rc 2 脚本的简化 upstart 脚本
start on startup stop on shutdown stop on runlevel-3 script set $(runlevel --set 2 || true) exec /etc/init.d/rc 2 end script |
initctl工具提供了类似于
telinit的功能,不过增加了一些特定于
upstart的特性。正如您前面看到的一样,您可以使用
initctl和
emit选项为
upstart生成一个事件。
list选项让您可以通过标识作业状态来深入了解系统操作。它告诉您目前正在等待哪些服务,以及哪些服务目前是活动的。
initctl工具还可以显示用于调试而接收的事件。
Upstart是
init的一个有趣的替代程序,并且具有一些独特的优点。实际上已经不存在什么理由再使用运行级别了,因为系统将充分利用硬件进行引导。任何没有给出的硬件都不会触发需要它的任务。
Upstart也可以很好地处理热插拔设备。例如,如果在完成系统引导很长时间以后插入了一块 PCMCIA 网卡,那就会生成 network-interface-added 事件。这个事件会引起动态主机配置协议(Dynamic Host Configuration
Protocol,DHCP)作业来对这个网卡进行配置,生成一个 network-interface-up 事件。当为这个新接口分配一个默认路由时,会生成一个
default-route-up 事件。此时,需要网络接口的作业(例如邮件服务器或 Web 服务器)就可以自动启动(如果接口消失,这些服务将会自动停止)。
使用 upstart
编译和安装
upstart非常简单,并且遵循典型的
configure、
make和
make install模式。
Upstart提供了一组示例作业,它们与典型的
init配置兼容。与
initng类似,新应用程序必须要根据需求编写自己的作业(可能还需要添加新事件)。不管怎样,部署新的
init系统都会有一些风险。不过
upstart的优点当然值得去冒这些风险并执行其他必要的操作。
正如上面介绍的一样,
initctl工具提供了人们对
telinit所期望的功能。不过
initctl也为跟踪和调试提供了附加功能。
本文中介绍的这两种方法 ——
initng和
upstart—— 并不是只有这两种程序可以替代
init。您还会找到其他的
init替代程序,例如
runit、
pardus、
minit和
einit。所有这些程序在 Linux 社区中都有一些支持者和一定的促进动力。现在,
upstart可能就是我们要了解的一个,因为它已经被流行的 Ubuntu 发行版采纳为
init的替代程序。更多信息请参看 参考资料。
在修改了系统引导进程后,理解修改的内容以及其如何影响系统引导的总时间会非常有帮助。Ziga Mahkovec 开发了一个非常有用的工具
bootchart,可以可视化地表示启动进程的组成。这个工具由几个元素组成,包括一个数据日志记录器工具和一个可视化工具。
数据日志记录器在(
bootchartd)是在
init进程中运行的(通常,在 grub 或 lilo.conf 文件中指定)。在
bootchartd完成初始化之后,就会将控制权交给真正的
init进程(通常是 /sbin/init)。
Bootchartd本质上是一个分析器,它每隔一段时间定期对环境进行采样(默认间隔是 200ms)。所谓对环境进行采样,就是说它可以读取当前 CPU 的统计信息、I/O 和空闲事件、磁盘使用情况以及每个活动进程的信息(通过
proc文件系统)。数据保存在一个临时文件(/var/log/bootchart.tgz)中用于稍后进行二次处理。
Bootchart然后会使用一个二次处理工具将原始数据转换成一个引导图。这个过程可以在本地使用一个 Java™ 应用程序(
bootchart发行版的一部分)来完成,不过更简单的方法是通过
bootchart主页上的一个 Web 表单来完成。图 2 展示了引导图表的部分示例。注意这些图将会非常大(这取决于所启动的服务和应用程序)。关于完整示例的链接,请参看 参考资料。
图 2. bootchartd 所创建的引导图片断
|
initng)到基于事件的解决方案(如
upstart),总会有一种优化解决方案能够满足您的要求。使用
bootchart包,您可以深入理解系统的引导时间是如何分配的,从而进一步进行优化。
参考资料
学习
您可以参阅本文在 developerWorks 全球网站上的 英文原文。
关于各种 Linux 发行版上的系统管理的观点,请参考 developerWorks 上的资源:
differentiating
UNIX and Linux。
尽管已经有点过时,不过这个 Red Hat 资源探究了 Linux 的不同 运行级别。
在 developerWorks 中国网站 Linux 专区 中可以找到为 Linux 开发人员准备的更多资源。
随时关注 developerWorks 技术活动 和 网络广播。
获得产品和技术
下一代
init系统(
initng)是替代
init系统的一个基于依赖关系的方法。
Ubuntu
upstart系统是替代
init系统的一个基于事件的方法。
Bootchart是一个用于引导过程的性能分析和可视化工具。它可以搜集系统初始化过程中的性能数据,然后在一条时间线上对其进行二次处理。
einit包是使用可扩展标记语言(XML)实现配置文件的初始化脚本的另一种方法。
另外一种有趣的
init并行化模式是
Pardus。这种方法不但可以删除 Linux 引导的串行特性,而且还通过使用 Python 语言增加了系统的灵活性。
runit
包是使用服务管理的
init方案的一个替代程序。
minit包是
init系统的一个小而全的版本。您可以研究
sysvinit的源代码。
定购免费的 SEK for Linux,这是 2 张 DVD,其中包含了 IBM 在 Linux 平台上的最新试用软件,包括 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere®。
使用 IBM 试用版软件 在 Linux 上构建您的下一个开发项目,可从 developerWorks 上直接下载。
讨论
通过参与 developerWorks blogs 加入 developerWorks 社区。
关于作者
M. Tim Jones 是一名嵌入式软件工程师,他是 GNU/Linux Application Programming、AI Application Programming 以及 BSD Sockets Programming from a Multilanguage Perspective 等书的作者。他的工程背景非常广泛,从同步宇宙飞船的内核开发到嵌入式架构设计,再到网络协议的开发。Tim 是位于科罗拉多州 Longmont 的 Emulex Corp. 的一名顾问工程师。 |
相关文章推荐
- 并行启动应用程序从而加速 Linux 的引导
- 并行启动应用程序从而加速 Linux 的引导
- 并行启动应用程序从而加速 Linux 的引导
- 并行启动应用程序从而加速 Linux 的引导
- android实现应用程序只有在第一次启动时显示引导界面 ,以后就不在显示
- 启动腾讯软件出现“应用程序无法启动并行配置不正确”解决
- 提高Linux系统性能加速网络应用程序
- 重装Windows系统后,Linux系统启动引导失败
- [转]提高 Linux 上 socket 性能,加速网络应用程序的 4 种方法
- 用win7的启动菜单实现linux系统引导
- win10 ssd+普通硬盘安装centos7 无法引导启动linux
- vs2008应用程序无法启动,因为应用程序的并行配置不正确
- Linux 学习笔记_5_Linux引导流程解析_2_inittab文件剖析及系统启动流程分析
- 如何解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- 应用程序无法启动,因为应用程序的并行配置不正确
- 解决"应用程序无法启动,因为应用程序的并行配置不正确"问题
- u盘安装linux,将grub安装到了u盘,导致没U盘系统无法引导启动的解决方法
- 使grub4dos引导启动linux
- 【OpsDev】双系统之Linux下修复win7启动引导
- Linux启动引导过程