本文向您描述了如何在不影响可用性的前提下加快 Linux 操作系统的引导速度。当然,这种方法要求您对系统服务及服务之间的依赖关系有所理解,如果它们可以并行启动,就让它们并行启动而不是串行启动。
毫无疑问 Linux 是一个优秀的系统,但仍然无法摆脱一个常见的责难(尤其是来自具有 Microsoft Windows 背景的人),那就是 Linux 系统从按下“on”键开始到可以使用,需要的时间太长。其实他们说的没错,Linux 确实需要比较长的引导时间。
在这里我所描述的加快 Linux 引导速度的技术虽然理解起来很简单,但真正实现却需要谨慎行事。我希望 Linux 的发行商能采用这种方法,这样用户就可以省去那些配置任务。不过如果您喜欢冒险,请继续阅读本文。
参考资料,可以找到可以下载UML的站点以及 developerWorks网站上关于UML的教程)。
使用UML您可以工作于一个测试系统,哪怕把这个测试系统完全破坏掉,也不会影响您正常的系统。
本文的第一部分介绍当 Linux 内核(Linux 机器的的“核心”)加载后,一个 Linux 系统怎样在后台启动。然后介绍加快您的系统引导速度的技术。
如果您对运行级和服务启动脚本已经熟悉,您可能希望直接跳转到 传统服务框架的局限。
一个 Linux 系统的引导过程可以分为几个阶段。本文并不会解释所有的不同阶段,因为我们所关心只是当内核加载后的那一个阶段。
您可以运行 /sbin/runlevel 命令来确定您的系统当前的运行级。(更多详细信息请查阅 man runlevel)。
当内核被加载并开始运行时会调用 /sbin/init 程序。这个程序以 root 身份运行,并且在开始引导时按照要求设定为“运行级”。(更多关于 init 程序的详细信息,请参考 man init)
一个 运行级仅仅是一个数字,Linux根据这个数字来区分不同类型的高层次配置,系统将按照不同的高层次配置来进行引导。由于绝大部分运行级数字都定义了明确的含义,因而它们基本上是“众所周知”的。Red Hat Linux 系统的主要运行级见表1。
表 1. Red Hat Linux运行级
运行级 |
说明 |
0 |
关闭 |
1 |
单一用户模式(一般仅用于管理目的) |
2 |
多用户模式,不允许使用网络 |
3 |
多用户模式,允许使用网络 |
4 |
没有用到的运行级 |
5 |
多用户模式,允许使用网络,X-Windows 方式(图形登录界面) |
6 |
重新引导 |
|
在 Red Hat 系统中,在运行 rc 脚本之前,init 将首先运行 /etc/rc.d/rc.sysinit 脚本,这个脚本执行那些必需的底层设置任务,比如设置系统时钟,检查磁盘错误,然后挂载文件系统。 | |
|
在一些 Linux 系统中,服务程序有时候是在 /etc/init.d 目录下。 | |
|
符号链接的名字可以用 egrep 正则表达式来描述,[SK][0-9]{2}[a-zA-Z]+。(更多详细信息请参阅 man egrep)。 | |
# cd /etc/rc.d/rc5.d
# ls -al
total 8
drwxr-xr-x 2 root root 4096 Jul 15 09:29 .
drwxr-xr-x 10 root root 4096 Jun 21 08:52 ..
lrwxrwxrwx 1 root root 19 Jan 1 2000 K05saslauthd -> ../init.d/saslauthd
lrwxrwxrwx 1 root root 20 Feb 1 2003 K15postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 13 Jan 1 2000 K20nfs -> ../init.d/nfs
lrwxrwxrwx 1 root root 14 Jan 1 2000 K24irda -> ../init.d/irda
lrwxrwxrwx 1 root root 17 Jan 1 2000 K35winbind -> ../init.d/winbind
lrwxrwxrwx 1 root root 15 Jan 1 2000 K50snmpd -> ../init.d/snmpd
lrwxrwxrwx 1 root root 19 Jan 1 2000 K50snmptrapd -> ../init.d/snmptrapd
lrwxrwxrwx 1 root root 16 Jun 21 09:43 K50vsftpd -> ../init.d/vsftpd
lrwxrwxrwx 1 root root 16 Jun 21 08:57 K73ypbind -> ../init.d/ypbind
lrwxrwxrwx 1 root root 14 Jun 21 08:54 K74nscd -> ../init.d/nscd
lrwxrwxrwx 1 root root 18 Feb 8 11:15 K92iptables -> ../init.d/iptables
lrwxrwxrwx 1 root root 19 Feb 1 2003 K95firstboot -> ../init.d/firstboot
lrwxrwxrwx 1 root root 15 Jan 1 2000 S05kudzu -> ../init.d/kudzu
lrwxrwxrwx 1 root root 14 Jun 21 08:55 S09isdn -> ../init.d/isdn
lrwxrwxrwx 1 root root 17 Jan 1 2000 S10network -> ../init.d/network
lrwxrwxrwx 1 root root 16 Jan 1 2000 S12syslog -> ../init.d/syslog
lrwxrwxrwx 1 root root 17 Jan 1 2000 S13portmap -> ../init.d/portmap
lrwxrwxrwx 1 root root 17 Jan 1 2000 S14nfslock -> ../init.d/nfslock
lrwxrwxrwx 1 root root 18 Jan 1 2000 S17keytable -> ../init.d/keytable
lrwxrwxrwx 1 root root 16 Jan 1 2000 S20random -> ../init.d/random
lrwxrwxrwx 1 root root 16 Jun 21 08:52 S24pcmcia -> ../init.d/pcmcia
lrwxrwxrwx 1 root root 15 Jan 1 2000 S25netfs -> ../init.d/netfs
lrwxrwxrwx 1 root root 14 Jan 1 2000 S26apmd -> ../init.d/apmd
lrwxrwxrwx 1 root root 16 Jan 1 2000 S28autofs -> ../init.d/autofs
lrwxrwxrwx 1 root root 14 Jan 1 2000 S55sshd -> ../init.d/sshd
lrwxrwxrwx 1 root root 20 Jan 1 2000 S56rawdevices -> ../init.d/rawdevices
lrwxrwxrwx 1 root root 16 Jan 1 2000 S56xinetd -> ../init.d/xinetd
lrwxrwxrwx 1 root root 14 Feb 1 2003 S58ntpd -> ../init.d/ntpd
lrwxrwxrwx 1 root root 13 Jun 21 10:42 S60afs -> ../init.d/afs
lrwxrwxrwx 1 root root 13 Jan 1 2000 S60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 16 Feb 8 17:26 S78mysqld -> ../init.d/mysqld
lrwxrwxrwx 1 root root 18 Jan 1 2000 S80sendmail -> ../init.d/sendmail
lrwxrwxrwx 1 root root 13 Jan 1 2000 S85gpm -> ../init.d/gpm
lrwxrwxrwx 1 root root 15 Mar 22 08:24 S85httpd -> ../init.d/httpd
lrwxrwxrwx 1 root root 15 Jan 1 2000 S90crond -> ../init.d/crond
lrwxrwxrwx 1 root root 13 Jan 1 2000 S90xfs -> ../init.d/xfs
lrwxrwxrwx 1 root root 17 Jan 1 2000 S95anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 13 Jan 1 2000 S95atd -> ../init.d/atd
lrwxrwxrwx 1 root root 15 Jun 21 08:57 S97rhnsd -> ../init.d/rhnsd
lrwxrwxrwx 1 root root 14 Jul 15 09:29 S98wine -> ../init.d/wine
lrwxrwxrwx 1 root root 13 Feb 8 17:26 S99db2 -> ../init.d/db2
lrwxrwxrwx 1 root root 11 Jun 21 08:52 S99local -> ../rc.local
#
|
这看起来好象是非常复杂的系统,但实际上它提供了极好的灵活性,因为如果您想临时禁止某个特定运行级中的服务,只要把适当的符号链接删除即可。不过,手工管理这些链接可能会让人感觉厌烦,并且容易出错(尤其当您累了的时候),所以可以采用一个相对好一些的方法,使用 chkconfig 命令。
|
如果您有一个新版本的 chkconfig ,您会在主输出的最后一部分看到有关 xinetd (Internet services daemon)的配置。为了减化说明,此部分没有列入清单2中。 | |
清单 2列出了这个命令的输出。您可以看到,每一行有八列。
chkconfig 命令还可以用来切换任何一个服务的开或关。详细信息请参考手册页(man chkconfig)。
afs 0:off 1:off 2:off 3:on 4:off 5:on 6:off
anacron 0:off 1:off 2:on 3:on 4:on 5:on 6:off
apmd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
autofs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
db2 0:off 1:off 2:off 3:on 4:off 5:on 6:off
firstboot 0:off 1:off 2:off 3:off 4:off 5:off 6:off
gpm 0:off 1:off 2:on 3:on 4:on 5:on 6:off
httpd 0:off 1:off 2:off 3:off 4:off 5:on 6:off
iptables 0:off 1:off 2:off 3:off 4:off 5:off 6:off
irda 0:off 1:off 2:off 3:off 4:off 5:off 6:off
isdn 0:off 1:off 2:on 3:on 4:on 5:on 6:off
keytable 0:off 1:on 2:on 3:on 4:on 5:on 6:off
kudzu 0:off 1:off 2:off 3:on 4:on 5:on 6:off
lpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
mysqld 0:off 1:off 2:off 3:on 4:off 5:on 6:off
netfs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
nfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
nfslock 0:off 1:off 2:off 3:on 4:on 5:on 6:off
nscd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
ntpd 0:off 1:off 2:off 3:on 4:off 5:on 6:off
pcmcia 0:off 1:off 2:on 3:on 4:on 5:on 6:off
portmap 0:off 1:off 2:off 3:on 4:on 5:on 6:off
postgresql 0:off 1:off 2:off 3:off 4:off 5:off 6:off
random 0:off 1:off 2:on 3:on 4:on 5:on 6:off
rawdevices 0:off 1:off 2:off 3:on 4:on 5:on 6:off
rhnsd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
saslauthd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
sendmail 0:off 1:off 2:on 3:on 4:on 5:on 6:off
snmpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
snmptrapd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
syslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
vsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
winbind 0:off 1:off 2:off 3:off 4:off 5:off 6:off
wine 0:off 1:off 2:on 3:on 4:on 5:on 6:off
xfs 0:off 1:off 2:on 3:on 4:on 5:on 6:off
xinetd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
ypbind 0:off 1:off 2:off 3:off 4:off 5:off 6:off
|
清单 2中第一列是服务的名字,接下来的列是运行级和每一个运行级中服务的状态。例如,ntpd (Network time daemon)服务被配置为只在运行级3中(多用户,无图形)和运行级5(多用户,有图形)中启动,sshd 服务在运行级2,3,4和5中都被切换到开的状态。
注意在运行级0和6中没有一个服务要启动。回顾表 1,原因显而易见。运行级1表示要关闭或停止系统,因此在机器将要“关闭”时,您不会想要 启动任何服务。运行级6中也是如此。
运行级1——“单一用户模式”——是一个特别的运行级,一般在系统出问题的时候使用。一直以来,在运行级1中运行的唯一一个应用程序是 shell,允许超级用户来修复系统或者让超级用户在一个安全的环境中修改系统。这样是安全的——就像它的名字“单一用户模式”的含意一样——只有超级用户可以访问系统。并且,联网是禁用的,所以没有人可以远程登录。如表 1所示,单一用户模式中运行的唯一一个服务是keytable,这样使得超级用户的键盘可以正常使用。
关键的是,只有当配置中的所有服务都启动以后,您才可以登录进入您的 Linux 系统。等待50个服务启动可能会需要若干分钟,而这本来应该是您享用Linux系统的时间。
我已经找到了一个加速这个过程的方法。注意这种方法不会停止任何服务。不管怎样,停掉那些不用的服务是很明智的,不仅是因为这样可以加快引导的速度(在机器可以登录之前需要运行的服务少了),而且,由于很多服务要以 root 用户身份来运行,停掉不用的服务会减少您的安全隐患。
扼要重述一下,当一个 Linux 系统引导时,它以一种连续的方式来运行所有的某个运行级所配置的所有服务—— 一个接一个地。这是一个耗时的操作。
或许一个很明显的加快服务启动速度的方法是并行地启动所有的服务,这样它们就可以同时启动。不幸的是,虽然这听起来很吸引人,却不可行。原因是各个服务之间存在依赖的关系。Linux没有把这些依赖关系完全显式地表示出来,但是事实上这些依赖关系是存在的。还记得我们先前讨论的关于链接名字格式的问题吗?在 “S”和“K”之后的两位数决定了链接(也就是它们指向的服务)的运行顺序。这些数字确定了一个硬性的顺序,这样一定程度上也强化了服务之间的依赖关系。
回顾 清单 1,我们可以看到 network 服务(S10network)将在ntpd服务(S58ntpd)之前运行。这是我们所期望的,因为 ntpd 服务要求网络可达,以使它可以连接一个本地时间服务器。不幸的是,这个硬性的顺序并不能告诉我们足够的信息,并且会让人误解。例如,在 清单 1中我们可以看到 lpd 服务(S60lpd)将在 network 服务之后运行。虽然这样对那些连接到网络并且使用网络打印机的 Linux 系统来说是正确的,但是这并不说明当背板上有一个 inkjet 打印机连接到本地系统时,lpd 服务还是必须要在 network 服务之后运行。实际上,在这种情况下,在启动 network 之前先启动 lpd 会更好一些。
再来看另外一个例子:crond (cron daemon)服务 (在 清单 1中的 S90crond)也是在 network 启动之后运行。可是,如果您没有使用远程机器文件的 cron 文件,那么就应该让 crond 在 network 之前启动。
由于我刚才介绍的 Linux 下启动服务的传统方法有一定的局限性,往往倾向于“安全第一",让所有的重要的服务先启动,然后再启动余下的那些。
所以,尽管我们不能并行地启动 所有的服务,但我们可以并行地启动那些 相互间没有依赖关系的服务。当这些相互间无依赖的服务启动以后,我们可以启动那些所有依赖条件已经满足(也就是说,那些服务所依赖的服务已经启动)的服务。然后重复这一过程,直到所有服务全部启动。
这个看起来是一个复杂的问题,不过幸运的是,已经有一个现成的可以用来解决这个问题的程序。这个程序不是别的,正是 make。
通常当编译软件时,make 会提供我们所需要的严密的框架。所有我们要做的就是告诉 make 什么是服务之间的依赖;它可以去做所有的计算交叉依赖的艰难工作,并且,使用它的鲜为人知的标记 -j ,它可以作为许多"作业"而 同步运行。
|
如果当您运行命令 /sbin/chkconfig --list时,您有可能会遇到一些您所不认识的服务,那么花一些时间去弄明白它。一个简单的方法是读那些控制相应服务的脚本中开头处的注释。 这样您就可以把不用的那些工具所对应的服务关掉。即便是您需要它,这样您也可以更加了解您的系统。
| |
ntpd : network
netfs : network
autofs : network
|
参考资料部分提供的压缩文件中有一个使用上述技术的样例实现。包括一个修改过的用于调用 make 命令的 rc 脚本,以及样例GNU makefile文件,分别是 runlevel.mk,start5.mk和stop5.mk。makefile 文件 runlevel.mk 是控制程序,start5.mk 文件和stop5.mk 文件分别是运行级5时启动和停止服务时的服务依赖描述文件。
注意所给出的启动和停止 makefile 文件提供的不是完全的服务间依赖关系列表,而仅仅是一个例子。同时也要注意,如果您不修改这些文件就在您的系统上使用,几乎不可能成功,因为您的服务列表可能和我的并不一样。
原文链接:http://www-128.ibm.com/developerworks/cn/linux/l-boot/index.html