linux系统启动流程详解

时间:2021-05-16 04:45:01

RHEL6 启动过程

在 Red Hat Enterprise Linux 6 中,sysvinit 软件包中的 init 已经由 Upstart 替换,它是基于事件的 init 系统。这个系统可处理在引导过程中的任务和服务启动,在关机过程中关闭它们并在系统运行时监控它们。rhel6的启动流程发生了比较大的变化。对于熟悉其流程非常重要,对系统的排错有很大的帮助。


1、BIOS加电,进行硬件自检。然后产生int 19的终端,读取第一个可引导的设备,比如自检,初始化各种芯片,控制器,与端口;包括显示器,内存,键盘,软驱,串口等等最终,POST(Power- On Self Test)执行INT 19h中断,找到可以启动的磁盘,并将boot程序装入内存,并将控制权交给OS的boot程序。当BIOS INT 19h被执行以后,系统进入OS Booting阶段。


2、一块硬盘,有一个主引导记录,就是0面0道1扇区,又称MBR。MBR是由 BIOS自动装载到内存中并CPU跳转过去执行的。主引导记录(Master Boot Record,缩写:MBR),又叫做主引导扇区,是计算机开机后访问硬盘时所必须要读取的首个扇区,它在硬盘上的三维地址为(柱面,磁头,扇区)=(0,0,1)。共512 Byte。


| | | |
| 引导代码 446 Byte | 分区表 64 Byte | 结束符2 Byte |
|_______|____|___ _|


3、读取第一个可引导的设备的MBR的BootLoader程序,在rhel系统上是Grub.
stage1:
/boot/grub中的stage1文件大小为512b,它是引导扇区中引导程序(前446字节为引导程序)的备份文件,功能是用来装载 stage1.5或stage2的。
stage1.5:
因为STAGE2较大,通常都是放在一个文件系统当中的,但是STAGE1并不能识别文件系统格式,所以才需要stage1.5来引导位于某个文件系统当 中的STAGE2,根据文件系统格式的不同,STAGE1.5也需要相应的文件,如:e2fs_stage1_5,fat_stage1_5,分别用于识 别 ext和fat的文件系统格式。但是,当stage1加载1.5时,原则上是不认识ext文件系统的,应该也是无法找到1.5程序的,而实际上在安装 grub时,程序已经把1.5程序写到硬盘最前面的32K中,因为紧连着MBR的一段硬盘空间通常是空白无用的,grub就把stage1.5程序写到这 个地方,这个地方没有文件系统,stage1程序可以直接去加载stage1.5。


4、Grub进程第二阶段引导,读取/boot/grub/grub.conf配置文件,根据配置文件中的定义,加载相应的内核,内核再加载相应的硬件驱动,进行必要的基础硬件初始化
stage2:
grub能让用户以选项方式将OS加载、改变参数、修改选项,这些全都是stage2程序的功能。stage2可以去获取grub.conf以及menu.lst等文件的内容。

[root@osdba~]# ls /boot/
config-2.6.32-71.el6.i686 <===系统kernel的配置文件,内核编译完成后保存的就是这个配置文件
efi <===Extensible Firmware Interface(EFI,可扩展固件接口)是 Intel 为全新类型的 PC 固件的体系结构、接口和服务提出的建议标准。
grub <===开机管理程序grub相关数据目录
initramfs-2.6.32-71.el6.i686.img <===虚拟文件系统文件(RHEL6用initramfs代替了initrd,他们的目的是一样的,只是本身处理的方式有点不同)
initrd-2.6.32-71.el6.i686.img <===此文件是linux系统启动时的模块供应主要来源,initrd的目的就是在kernel加载系统识别cpu和内存等内核信息之后,让系统进一步知道还有那些硬件是启动所必须使用的;
symvers-2.6.32-71.el6.i686.gz <===模块符号信息
System.map-2.6.32-71.el6.i686 <===是系统kernel中的变量对应表;(也可以理解为是索引文件)
vmlinuz-2.6.32-71.el6.i686 <===系统使用kernel,用于启动的压缩内核镜像。


[root@osdba~]# cat /boot/grub/grub.conf
# grub.conf generated by anaconda
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/sda3
# initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux (2.6.32-71.el6.i686)
root (hd0,0)
kernel /vmlinuz-2.6.32-71.el6.i686 ro root=UUID=bfd97ccd-15df-4e0f-8a66-b2da62213f62
rd_NO_LUKS rd_NO_LVM rd_NO_MD rd_NO_DM
LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us crashkernel=auto rhgb quiet
initrd /initramfs-2.6.32-71.el6.i686.img

default #启动系统时在人为不干预的情况下,默认读取哪一个title,如果安装了多个不同版本内核或者安装了不用的操作系统,默认会产生多个title,#0第一个,1第二个,以此类推。

timeout #开机等待用户的超时时间,单位为秒。在超时时间结束时,如果用户没有人为选择,则以default指定的title读取。

splashimage=(hd0,0)/grub/splash.xpm.gz #grub的背景图案
hiddenmenu #隐藏菜单

title Red Hat Enterprise Linux (2.6.32-71.el6.i686) #title后为指定的菜单名字
root (hd0,0)#root 这里指定boot分区所在磁盘及分区,hd代表硬盘(不区分IDE、SCSI),第一个0:第一个硬盘,第二个0:第一个分区。这里的意思是定义第一个硬盘的第一个分区为boot分区。

kernel /vmlinuz-2.6.32-71.el6.i686#由boot loader的管理而开始读取内核文件后,接下来,Linux 就会将内核解压缩到内存当中, 并且利用内核的功能,开始测试与驱动各个周边设备,包括储存设备、CPU、网卡、声卡等等。 此时 Linux 内核会以自己的功能重新检测一次硬件,而不一定会使用 BIOS 检测到的硬件信息。也就是说,内核此时才开始接管 BIOS 后的工作。内核一般来说,它会被放置到 /boot 里面,并且取名为 /boot/vmlinuz。

ro root=UUID=bfd97ccd-15df-4e0f-8a66-b2da62213f62#Linux内核是可以通过动态加载内核模块的 (就请想成驱动程序即可),这些内核模块就放在 /lib/modules/目录内。由于模块放到磁盘根目录内(这就是为什么/lib不可以与/ 分别放在不同的分区原因), 因此在开机的过程中内核必须要挂载根目录,这样才能够读取内核模块提供加载驱动程序的功能。 而且为了担心影响到磁盘内的文件系统,开机过程中根目录是以只读的方式来挂载的。

rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD:为了加速引导启动进程,可以指定磁盘是否加密、语言环境、不启用LVM、RAID、键盘等等,节省启动的时间

SYSFONT=latarcyrheb-sun16 KEYTABLE=us:对于有加密磁盘的系统启动,可以指定键盘规格和字体显示等
quiet:启动过程中只有重要信息显示,类似硬件自检的消息不回显示
rhgb:RedHat graphics boot,就是会看到图片来代替启动过程中显示的文本信息,这些信息在启动后dmesg也可以看到
crashkernel=auto#kdump使用的内存空间,Kdump 是一种基于 kexec 的 Linux 内核崩溃捕获机制,将 kernel 崩溃前的内存镜像保存,程序员通过分析该文件找出 kernel 崩溃的原因,从而进行系统改进

【注意】
kernel与initrd这两个设置项中,指定的路径都是绝对路径。因为这两个文件都存放在/boot目录。而且/boot所在的分区已经指定,所以就无需再指明kernel与initrd在哪个分区了。如果boot分区为独立分区,那么前面的/boot省略掉。如果boot分区为非独立分区,那么必须加上/boot。

【例如】
独立分区:kernel /vmlinuz-2.6.32-220.el6.x86_64
非独立分区:kernel /boot/vmlinuz-2.6.32-220.el6.x86_64

rd_NO_LUKS rd_NO_LVM rd_NO_MD rd_NO_DM
LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc
KEYTABLE=us crashkernel=auto rhgb quiet
Speeding up the Boot Process
If you want to speed up the boot process, you can specify as much information for dracut (dracut是下一代的 initramfs 系统)on the kernel command as possible. For example, you can tell dracut, that you root partition is not on a LVM volume or not on a raid partition, or that it lives inside a specific crypto LUKS encrypted volume. By default, dracut searches everywhere. A typical dracut kernel command line for a plain primary or logica partition would contain:
rd_NO_LUKS rd_NO_LVM rd_NO_MD rd_NO_DM (elinks /usr/share/doc/dracut-004/dracut-rhel6.html or man 8 dracut)
This turns off every automatic assembly of LVM, MD raids, DM raids and crypto LUKS.
Keyboard Settings
If you have to input passwords for encrypted disk volumes, you might want to set the keyboard layout and specify a display font.
A typical german kernel command would contain:
LANG=de_DE.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=de-latin1-nodeadkeys

initrd /initramfs-2.6.32-71.el6.i686.img#boot loader装入kernel,然后kernel需要执行/sbin/init,读取这个文件就必须先mount根文件系统,在早期的linux系统中,一般只有硬盘或者软盘被用来作为linux根文件系统的存储设备,因此也就很容易把这些设备的驱动程序集成到内核中,随着硬件和技术的发展,现在根文件系统可能位于各种存储设备上,比如一个网络存储如NFS上,可能由于RAID而散布于多 个设备上,可能位于一个加密设备上需要提供用户名和密码,可能是scsi、sata,u-disk设备等等等,因此把这些设备的驱动代码全部编译到内核中显然就不是 很方便。为了应付这种局面,先后出现两种机制来作为boot loader装载kernel到真正的/sbin/init执行这个启动过程的桥梁: initrd和nitramfs

initrd:
一、 initrd出现的背景
在早期的linux系统中,一般只有硬盘或者软盘被用来作为linux根文件系统的存储设备,因此也就很容易把这些设备的驱动程序集成到内核中。但是现在 的嵌入式系统中可能将根文件系统保存到各种存储设备上,包括scsi、sata,u-disk等等。因此把这些设备的驱动代码全部编译到内核中显然就不是 很方便。

虚拟文件系统(Initial RAM Disk) 一般使用的文件名为 /boot/initrd ,这个文件的作用是,能够通过 boot loader 来加载到内存中, 然后这个文件会被解压缩并且在内存当中仿真成一个根目录, 且此仿真在内存当中的文件系统能够提供一支可执行的程序,通过该程序来加载开机过程中所最需要的内核模块,通常这些模块就是 USB, RAID, LVM,SCSI 等文件系统与磁盘接口的驱动程序。等载入完成后,会帮助内核重新呼叫 /sbin/init 来开始后续的正常开机流程。
Initial RAM Disk是一个基于ram的块设备,因此它占据了一块固定的内存,而且事先要使用特定的工具比如mke2fs格式化,还需要一个文件系统驱动来读写其上的 文件。如果这个disk上的空间没有用完,这些未用的内存就浪费掉了,并且这个disk的空间固定导致容量有限,要想装入更多的文件就需要重新格式化。由 于Linux的块设备缓冲特性,ram disk上的数据被拷贝到page cache(对于文件数据)和dentry cache(对于目录项),这个也导致内存浪费。
initramfs:
最初的想法是Linus提出的: 把cache当作文件系统装载。 他在一个叫ramfs的cache实现上加了一层很薄的封装,其它内核开发人员编写了一个改进版tmpfs, 这个文件系统上的数据可以写出到交换分区,而且可以设定一个tmpfs装载点的最大尺寸以免耗尽内存。initramfs就是tmpfs的一个应用。 Linux 2.6 kernel提出了这种新的实现机制,即 initramfs。顾名思义,initramfs只是一种RAM filesystem而不是disk。
initramfs的优点:
(1)tmpfs随着其中数据的增减自动增减容量。
(2)在tmpfs和page cache/dentry cache之间没有重复数据。
(3)tmpfs重复利用了Linux caching的代码,因此几乎没有增加内核尺寸,而caching的代码已经经过良好测试,所以tmpfs的代码质量也有保证。
(4)不需要额外的文件系统驱动。
另外,initrd机制被设计为旧的”root=” 机制的前端,而非其替代物,它假设真正的根设备是一个块设备,而且也假设了自己不是真正的根设备,这样不便将NFS等作为根文件系统,最后 /linuxrc不是以PID=1执行的,因为1这个进程ID是给/sbin/init保留的。initrd机制找到真正的根设备后将其设备号写入 /proc/sys/kernel/real-root-dev,然后控制转移到内核由其装载根文件系统并启动/sbin /init。initramfs则去掉了上述假设,而且/init以PID=1执行,由init装载根文件系统并用exec转到真正的/sbin /init,这样也 导致一个更为干净漂亮的设计。
下面让我们来看看initrd文件的具体内容,
[root@osdba~]# mkdir /tmp/initramfs/
[root@osdba~]# cp /boot/initramfs-2.6.32-71.el6.i686.img /tmp/initramfs/
[root@osdba~]# cd /tmp/initramfs/
[root@osdba initramfs]# file initramfs-2.6.32-71.el6.i686.img
initramfs-2.6.32-71.el6.i686.img: gzip compressed data, from Unix, last modified: Wed Aug 24 23:14:47 2011, max compression
我们可以看到,这个文件是GZIP压缩的文件,我们把后缀改成gz,然后再进行解压
[root@osdba initramfs]# mv initramfs-2.6.32-71.el6.i686.img initramfs-2.6.32-71.el6.i686.img.gz
[root@osdba initramfs]# gunzip initramfs-2.6.32-71.el6.i686.img.gz
解压后,我们再来看看这个文件是什么类型的
[root@osdba initramfs]# file initramfs-2.6.32-71.el6.i686.img
initramfs-2.6.32-71.el6.i686.img: ASCII cpio archive (SVR4 with no CRC)
是cpio压缩成的文件
[root@osdba initramfs]# cpio -idmv < initramfs-2.6.32-358.el6.i686.img
[root@osdba initramfs]# ls -l
total 29708
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 bin
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 cmdline
drwxr-xr-x. 3 root root 4096 Sep 19 14:52 dev
-rw-r–r–. 1 root root 18 Sep 19 14:52 dracut-004-32.el6
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 emergency
drwxr-xr-x. 7 root root 4096 Sep 19 14:52 etc
-rwxr-xr-x. 1 root root 8088 Sep 19 14:52 init
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 initqueue
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 initqueue-finished
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 initqueue-settled
-rw-r–r–. 1 root root 30326784 Sep 19 14:57 initramfs-2.6.32-71.el6.i686.img
drwxr-xr-x. 9 root root 4096 Sep 19 14:52 lib
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 mount
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 pre-pivot
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 pre-trigger
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 pre-udev
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 proc
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 sbin
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 sys
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 sysroot
drwxr-xr-x. 2 root root 4096 Sep 19 14:52 tmp
drwxr-xr-x. 6 root root 4096 Sep 19 14:52 usr
drwxr-xr-x. 3 root root 4096 Sep 19 14:52 var
看结果,和我们系统中的/很类似。(有兴趣,慢慢了解)


5、在内核加载完毕、进行完硬件检测与驱动程序加载后,此时主机硬件已经准备就绪了,这时候内核会主动的呼叫第一支程序,那就是 /sbin/init。/sbin/init 最主要的功能就是准备软件执行的环境,包括系统的主机名、网络设定、语言、文件系统格式及其他服务的启动等。 而所有的动作都会通过 init的配置文件/etc/inittab来规划,而inittab 内还有一个很重要的设定内容,那就是默认的 runlevel (开机运行级别)。先来看看运行级别Run level,Linux就是通过设定run level来规定系统使用不同的服务来启动,让Linux的使用环境不同。我们来看看这个inittab文件里面的支持级别(RHEL6系统里面的,和以前的其它版本有很大的差别).

[root@osdba~]# cat /etc/inittab
# inittab is only used by upstart for the default runlevel
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.

# System initialization is started by /etc/init/rcS.conf

# Individual runlevels are started by /etc/init/rc.conf

# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf

# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.

# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).

# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this) (系统直接关机)
# 1 - Single user mode (单用户模式,用在系统出问题时的维护)
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking) (类似底下的 runlevel 3,但无 NFS 服务)
# 3 - Full multiuser mode (完整含有网络功能的字符模式)
# 4 - unused (系统保留,未使用)
# 5 - X11 (与 runlevel 3 类似,但加载使用 X Window)
# 6 - reboot (Do NOT set initdefault to this) (重新启动)

id:5:initdefault:
注意:0, 4, 6 不是关机、重新启动就是系统保留的,所以不能将预设的run level设定为这三个值。
RHEL6系统上的这个文件和以前的版本有很大的差别,目前这个文件只能设置运行级别,其它的相关配置文件,在此文件中已经做了说明如:
System initialization is started by /etc/init/rcS.conf
Individual runlevels are started by /etc/init/rc.conf
Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,with configuration in /etc/sysconfig/init.
从这个文件我们已经看出,红帽已经使用新的Upstart启动服务来替换以前的init.在RHEL6的版本中,我们可以把/etc/init/这个目录里面的内容,看成是以前/etc/inittab这个文件里的拆分。

我们可能通过man inittab来查看
DESCRIPTION
The /etc/inittab file was the configuration file used by the original
System V init(8) daemon.
The Upstart init(8) daemon does not use this file, and instead reads
its configuration from files in /etc/init. See init(5) for more
details.
UpStart: 基于事件的启动系统
Sysvinit:基于结果的启动系统
SysVinit守护进程(sysvinit软件包)是一个基于运行级别的系统,它使用运行级别(单用户、多用户以及其他更多级别)和链接(位于/etc /rc?.d目录中,分别链接到/etc/init.d中的init脚本)来启动和关闭系统服务。
Upstart init守护进程(upstart软件包)则是基于事件的系统,它使用事件来启动和关闭系统服务。几个很重要的定义
event: 事件, 是指系统状态的一种改变,这种改变会被通知给init进程。举例来说,boot loader会触发startup事件,系统进入runlevel 2的时候会触发runlevel 2事件,某个文件系统被挂载时会触发path-mounted事件, USB设备的插拔也都会产生相应的事件。这些时间会被通知给init进程,然后init进程来决定系统如何处理这些事件
job: 作业,一项作业是init进程读入的一系列指令。你可以使用initctl start或initctl stop命令来开始或停止某项作业,这是调用作业的一种方式。另一种方式是当系统被告知发生什么事件event后,运行该事件所对应的作业。可用sudo initctl list命令列出所有系统作业的运行状态。
task: 任务, a job that performs its work and returns to a waiting state when it is done. 中文是一种完成指定工作后进去等待状态的作业。
service: 服务,a job that does not normally terminate by itself. 举个例子来说, gettys 是以服务来实现的。 init进程监视所有服务,并在服务失败的时候重启服务。
原有的System V init启动过程的缺点是,它基于包含了大量启动脚本的runlevel目录。而Upstart则是事件驱动型的,因此,它只包含按需启动的脚本,这将使 启动过程变得更加迅速。经过良好调优并使用Upstart启动方式的Linux服务器的启动速度要明显快于原有的使用System V init的系统。
为了使Upstart更容易理解,它仍然使用了一个init进程。所以,你仍然可以看到/sbin/init,它是所有服务的根进程。
有一个好消息,那就是RHEL 6对启动过程的改变很少。你还是可以处理那些在目录/etc/init.d中的包含服务脚本的服务,所以runlevel的概念一直存在。因此,在使用 yum增加一个服务后,照样可以像以前那样使用chkconfig命令激活它。此外,仍然可以用service命令来启动它。


6、System initialization is started by /etc/init/rcS.conf
[root@osdba~]# cat /etc/init/rcS.conf
# Note: there can be no previous runlevel here, if we have one it’s bad
# information (we enter rc1 not rcS for maintenance). Run /etc/rc.d/rc
# without information so that it defaults to previous=N runlevel=S.
console output
exec /etc/rc.d/rc.sysinit


/etc/rc.d/rc.sysinit 这个文件做了哪些工作:
1、获得网络环境
2、挂载设备
3、开机启动画面Plymouth(取替了过往的 RHGB)
4、判断是否启用SELinux
5、显示于开机过程中的欢迎画面
6、初始化硬件
7、用户自定义模块的加载
8、配置内核的参数
9、设置主机名
10、同步存储器
11、设备映射器及相关的初始化
12、初始化软件磁盘阵列(RAID)
13、初始化 LVM 的文件系统功能
14、检验磁盘文件系统(fsck)
15、磁盘配额(quota)
16、重新以可读写模式挂载系统磁盘
17、更新quota(非必要)
18、启动系统虚拟随机数生成器
19、配置机器(非必要)
20、清除开机过程当中的临时文件
21、创建ICE目录
22、启动交换分区(swap)
23、将开机信息写入/var/log/dmesg文件中
这个文件里面的许多预设配置文件在/etc/sysconfig/这个目录当中,要想更多的系统启动信息,大家可以到/var/log/dmesg文件中查看,也可以用dmesg命令来查看。


7、Individual runlevels are started by /etc/init/rc.conf
[root@osdba~]# cat /etc/init/rc.conf


# rc - System V runlevel compatibility
#
# This task runs the old sysv-rc runlevel scripts. It
# is usually started by the telinit compatibility wrapper.





start on runlevel [0123456]
stop on runlevel [!$RUNLEVEL]
task
export RUNLEVEL
console output
exec /etc/rc.d/rc $RUNLEVEL

系统服务的启动经过 /etc/rc.sysinit 的系统模块与相关硬件信息的初始化后,RHEL6系统应该已经能顺利工作了。但还需要启动一些为我们提供服务的服务。这个时候,依据在/etc /inittab里面run level的设定值,就可以来决定启动的服务项目了。大家可以打开/etc/rc这个文件来研究.

以运行级别3为例
[root@osdba~]# ls /etc/rc3.d/
K01certmonger K80sssd S08iptables S25netfs
K01smartd K84wpa_supplicant S10network S26acpid
K02oddjobd K86cgred S11auditd S26haldaemon
K10psacct K87restorecond S12rsyslog S26udev-post
K10saslauthd K88nslcd S13cpuspeed S28autofs
K50dnsmasq K89rdisc S13irqbalance S55sshd
K50netconsole K95cgconfig S13rpcbind S64mysqld
K60nfs K95firstboot S15mdmonitor S80postfix
K69rpcsvcgssd K99stap-server S22messagebus S82abrtd
K73ypbind S00microcode_ctl S23NetworkManager S85httpd
K74nscd S01sysstat S24avahi-daemon S90crond
K74ntpd S02lvm2-monitor S24nfslock S95atd
K75ntpdate S03vmware-tools S24rpcgssd S97rhnsd
K80kdump S08ip6tables S24rpcidmapd S99local
在这个目录下的文件主要具有2个特点:
1、全部以Sxx或Kxx(xx为数字)开头
2、全部是连结文件,连结到/etc/init.d/

现在来说明一下这些的目的
S表示启动服务
K表示停止服务
后面的数字是启动的先后顺序

以S55sshd来举例
[root@osdba~]# ls -l /etc/rc3.d/S55sshd
lrwxrwxrwx. 1 root root 14 Aug 24 23:08 /etc/rc3.d/S55sshd -> ../init.d/sshd
意思就是
/etc/rc3.d/S55sshd = /etc/init.d/sshd start


8、用户自定义开机启动脚本
上面讲到的都是一些系统服务,Linux系统容许安装其它的软件来提供服务,那我想要自己安装的服务也要在开机启动,那怎么办,没有关系,找 /etc/rc.local 来完成。这就是我们要讲的用户自定义开机启动脚本。我们只要把想启动的脚本写到这个文件中,开机就能启动了,注意一点,写在这里面的脚本要使用绝对路径。


9、在/etc/init/start-ttys.conf中我们可以看到有4个运行级别([2-5])。我们可以用[Ctrl+Alt+F1~F6]来切换终端。如果要切换到X window终端我们可以用
[Ctrl+Alt+F1]

[root@osdba~]# cat /etc/init/start-ttys.conf
#
This service starts the configured number of gettys.
start on stopped rc RUNLEVEL=[2345]
env ACTIVE_CONSOLES=/dev/tty[1-6]
env X_TTY=/dev/tty1
task
script
. /etc/sysconfig/init
for tty in $(echo $ACTIVE_CONSOLES) ; do
[ "$RUNLEVEL" = "5" -a "$tty" = "$X_TTY" ] && continue
initctl start tty TTY=$tty
done
end script

注:虚拟机个与真实的环境还是有区别的,有很多快捷键是冲突的,所以这个需要自行实验获得。


10、加载终端或X-Window接口,在完成了系统所有服务的启动后,接下来Linux就会启动终端或者是X Window来等待使用者登陆了!
/sbin/mingetty 或者 /etc/X11/prefdm

在文件/etc/sysconfig/init中还有一些额外的配置。在这里,定义了一些参数来决定启动信息的格式。除了那些不很重要的设置,有三行我们需要注意:
AUTOSWAP=no
ACTIVE_CONSOLES=/dev/tty[1-6]
SINGLE=/sbin/sushell
AUTOSWAP:这一行的值你可以设定为Yes,这样可以让你的系统能够自动检测交换分区。使用此选项意味着你再也不必在/etc/fstab中挂载交换分区了。
ACTIVE_CONSOLES:这一行决定了虚拟控制台的创建。在大多数情况下,tty[1-6]工作得很好,同时这个选项也允许您分配更多或者更少的虚拟控制台。但是要注意,不要使用tty [1-8],因为tty7是专门为图形界面预留的。
SINGLE=/sbin/sushell:这一行可以有两个参数:/sbin /sushell(系统默认的参数),它会在启动单用户模式时将你带入一个root的 shell,参数/sbin/sulogin会在单用户模式启动之前弹出一个登录提示,你必须输入root账户的密码才能继续下去。


下面是RHEL6上面Upstart大致的一个启动过程:
1.内核启动init
2.系统初始化:(/etc/init/rcS.conf exec /etc/rc.d/rc.sysinit)
3.init找到/etc/inittab文件,确定默认的运行级别(X) (/etc/init/rcS.conf exec telinit $runlevel)
4.触发相应的runlevel事件(/etc/init/rc.conf exec /etc/rc.d/rc $RUNLEVEL)
5.开始运行/etc/rc.d/rc,传入参数X
6./etc/rc.d/rc脚本进行一系列设置,最后运行相应的/etc/rcX.d/中的脚本
7./etc/rcX.d/中的脚本按事先设定的优先级依次启动
8.最后执行/etc/rc.d/rc.local
9.加载终端或X-Window接口
想要了解更多的内容,请大家打开/etc/init/这个目录里面的文件看看。

运行级别的切换
通过上面的学习,我们知道run level是在/etc/rc.sysinit 执行完毕之后,而run level 的不同
之处仅是/etc/rc[0-6].d 里面启动的服务不同而已。
如果我们切换run level只需要停止与启动一些服务就OK,那么要如何来实现,其它很简单,用init n(数字)来切换。

[root@osdba~]# runlevel
N 5
5:当前的运行级别
N:在当前运行级别之前运行过什么运行级别,因为例中开机就是运行级别5,之前没有运行过其他运行级别,所以是N
[root@osdba~]# init 3

With RHEL6 having been released last November, half a year of aging has given me the opportunity to let some of its new features sink in. Definitely my 2 favorites are the introduction of upstart, to replace the aging Sysv init startup mechanism, and the introduction of advanced resource management with Cgroups.
Upstart has been available in Ubuntu since the release of edgy in 2006, and soon after it got picked up by other distributions as well. Upstart is an event-driven init daemon. As a consequence, unlike the previous requirement of having multiple runlevels, with each service defined to start in a particular sequence, Upstart will only start a service if there is an external event requiring it. i.e. It will only start Bluetooth services if there is Bluetooth hardware detected. This has the benefit that a large part of the service configuration is handled automatically and since only necessary services will run, you will have faster startup times and less resource consumption. Upstart still regards a change in runlevel as an event, so most services will still use their old rc style init scripts. As a consequence you can still use chkconfig to control these startup scripts or use the service command to manipulate these services. But for other functionalities, like setting up serial console, you will have to use an upstart job instead of the old way of doing it through inittab.
One good example is when you want to setup a serial console for qemu if you are testing rhel6 in a KVM virtual machine. By default the upstart script /etc/init/serial.conf will start a serial console if the primary console in grub is set to a serial console. If you want a serial console that is not the primary console, you will have to create your own upstart script:
[root@localhost ~]# cat /etc/init/Stty.conf
stop on runlevel [016]
start on runlevel [345]
respawn
instance /dev/ttyS0
exec /sbin/mingetty /dev/ttyS0
The first 2 lines of the script are called the event definition. Upstart needs to now for each service defined in /etc/init, what event will trigger a change in the state of the service. In this case we tell upstart to start the service in runlevels 3, 4 and 5 and to stop the service in runlevel 0, 1 and 6
The rest of the script is what is called the process definition. Here you define what to run and how to run it. In this case we tell upstart to respawn the getty process if it dies, to ensure that there is only one instance running that uses /dev/ttyS0 and we specify the getty command to run.
Now that we’ve create the upstart service we can manipulate it with the initctl tool:
[root@localhost ~]# initctl start Stty
[root@localhost ~]# initctl status Stty
Stty (/dev/ttyS0) start/running, process 18425
Now that we have a serial console running we can connect to it on the hardware node:
[:root@somehost:/root]$ virsh list
Id Name State

2 test running
[:root@somehost:/root]$ virsh console 2
The version of upstart in RHEL 6 lacks some of the more recent features introduced in Ubuntu like the ability to schedule cron – like jobs and a replacement for inetd with the socket upstart event. I hope these are backported to RHEL 6 soon.