Linxu系统的启动过程
启动流程
1、引导Linux启动是从BIOS中的地址0xFFFF0处开始的,BIOS由两部分组成:POST代码和运行时服务,运行时服务是为操作系统提供一些接口,如温度检测等。
-
BIOS的第一个步骤是加电自检(POST),完成对硬件的的检测,如某些硬件出现错误无法通过检测就导致系统无法启动,POST完成之后将被清出内存;
-
BIOS的第二个步骤是进行设备的枚举和初始化,按CMOS的设置搜索处于活动状态并且可引导的设备(floppy、CD-ROM、USB、Disk、NFS),加载主引导记录(MBR),到内存。此时BIOS将控制权交给Boot Loader
2、MBR的前 446 个字节是主引导加载程序(Boot Loader),其中包含可执行代码和错误消息文本。接下来的 64 个字节是分区表,其中包含 4 个分区的记录(每个记录16 bytes)。MBR 以两个特殊数字(0xAA55)结束。这个数字会用来进行 MBR 的有效性检查。
-
Boot Loader就是stage1,通过内置的地址引导了stage1_5 的引导加载程序加载/boot分区,进而加载stage2。MBR中的Boot Loader备份在了 /boot/grub/stage1 中
-
stage1_5在/boot/grub目录,用于识别内核所在分区的文件系统类型,是Boot Loader所处的 stage1 加载 stage2 的过渡,在这之后才能进入Grub引导程序。
3、Grub引导程序处于stage2,通过读取 /etc/grub.conf 文件,显示出内核列表,指定了内核镜像和 initrd 所在的分区为root,设定内核参数,并加载vmlinuz和initramfs这两个文件到内存中。在这一阶段可以编辑启动项目如指定根分区root,内核kernel,initrd镜像等;也可以进入grub command line手动写启动信息。
事实上,GRUB(GRand Unified Bootloader)管理开机启动的过程分成了三个阶段stage1/stage1.5/stage2。其中stage1主要负责BIOS和GRUB之间的交接。这部分才是真正放在MBR中的bootloader。而后stage1.5是连接stage1和stage2之间的通道,起着过渡的作用。最后才是GRUB中真正核心的部分stage2,它可以让用户以选项的方式将操作系统加载、修改选项和内核参数。
4、当内核映像被加载到内存中,并且stage2 的引导加载程序释放控制权之后,内核阶段就开始了,内核在完成自身的初始化之后进行探测可识别的所有硬件设备,由于内核中只包含了少量的硬件驱动,此时会借助内存中的initrd根文件系统加载相关驱动程序。当内核具备访问根文件系统功能时,initrd根文件系统将被卸载,并挂载真正的根文件系统。这就是内核的初始化过程,系统已经脱离了 /boot 分区,独立存活在内存中。
-
vmlinuz-xxx内核镜像是一个 zImage(压缩映像,小于 512KB)或一个 bzImage(较大的压缩映像,大于 512KB),它是使用 zlib 进行压缩过的内核文件
-
initramfs-xxx.img是由stage2 引导加载程序加载到内存中的,它会被复制到 RAM 中并挂载到系统上。这个 initrd 会作为 RAM 中的临时根文件系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。initrd文件包括可加载模块的驱动程序,为内核提供可访问磁盘和磁盘上的文件系统的接口,并为其他硬件提供了驱动程序。由于根文件系统是磁盘上的一个文件系统,因此内核通过initrd取得根分区的访问,并挂载真正的根文件系统。这是一个解包的initramfs镜像文件:
-
内核非常小,rpm -ql kernel看到大部分驱动模块都在安装内核时放在了/lib/modules/version/目录下,只有编译内核过程中被选择的模块才会成为内核镜像的一部分,还有一部分驱动模块存放在initfd镜像中,这些驱动模块确保了Linux内核可以在众多的架构上运行,并且兼容绝大多数硬件平台。
5、内核初始化的最后一步就是启动 init
进程。在init 以守护进程方式存在,是所有其他进程的祖先(PID=1
),init 进程非常独特,能够完成其他进程无法完成的任务。
-
在
CentOS 5
中使用sysvinit
初始化系统:sysvinit 就是 system V 风格的 init 系统,顾名思义,就是源于 System V 系列 UNIX -
init 通过读取 ‘
/etc/inittab
’ 文件完成系统初始化的过程: -
inittab文件
-
选择runlevel :Sysvinit 读取 ‘
/etc/inittab
’ 文件中是否含有 ‘initdefault’ 项,有则init 将启动默认运行的模式。如果没有默认的运行模式,将进入系统控制台,手动决定进入何种运行模式。 -
who -r 与 runlevel #查看当前的runlevel
-
runlevel通常会 7 种模式,即runlevel 0 ~ 6 。
通常:
# 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)
# 3 – Full multiuser mode
# 4 – unused
# 5 – X11
# 6 – reboot (Do NOT set initdefault to this)
. 系统选择进入 runlevel
. 运行系统初始化脚本,即/etc/rc.d/rc.sysinit
. 运行指定运行级别对应的目录下的脚本,即/etc/rc.d/rc#.d/目录下的服务脚本
. 捕获组合键的定义
. 定义电源 fail/restore 脚本
. 启动 getty 和虚拟控制台
字段定义格式及含义 id:runlevels:action:process
. id:标识符
. runlevels:在哪个级别运行此行
. action:在什么情况下执行此行
. process:要运行程序
[action]
. initdefault:设定默认运行级别
. sysinit:系统初始化
. wait:等待级别切换至此级别时执行
. respawn:一旦程序终止,会重新启动
-
/etc/rc.d/rc.sysinit
-
运行 rc.sysinit 以便执行一些重要的系统初始化任务。在RHEL 5中rc.sysinit 主要完成以下这些工作:
-
激活 udev 和 selinux
-
设置定义在/etc/sysctl.conf 中的内核参数
-
设置系统时钟
-
加载 keymaps
-
使能交换分区
-
设置主机名(hostname)
-
根分区检查和 remount
-
激活 RAID 和 LVM 设备
-
开启磁盘配额
-
检查并挂载所有文件系统
-
清除过期的 locks 和 PID 文件
-
/etc/rc.d/rc 和/etc/rc.d/rc#.d/
-
rc是个脚本,后面接参数,如:l5:5:wait:/etc/rc.d/rc 5 ,这里的wait意味着init系统将等待rc启动服务脚本。
-
rc 根据 runlevel 执行rc#.d 目录下启动脚本。每个 runlevel 都有一个对应的 rc#.d 目录
-
在这些目录下存放着很多不同的脚本,文件名以
S 开头
的脚本表示在当前runlevel中启动,K开头
的脚本表示不在当前runlevel中启动 -
在/etc/rc.d/rc#.d 目录下的脚本其实都是一些软链接文件,真实的脚本文件存放在
/etc/init.d
目录下,也就是说在/etc/init.d目录下的文件会自动
以S##script或K##script的软链接
存在于各 runlevel 的目录下 -
chkconfig –levle comm off实质上就是把S##script 改成了 K##script文件。注意这里的数字是在脚本内部定义的。自定义服务脚本时,定义的S数字尽量大,以免依赖的服务还没有启动。当使用 init #命令切换runlevel时,有些服务被关闭,此时定义的K数字尽量小,在依赖服务关闭前停止。
-
/etc/rc.d/rc.local
-
rc#.d/
S99local
文件没有链接至/rc.d/init.d/而是rc#.d/S99local -> ../rc.local,因此,命令放置于/etc/rc.d/rc.local
目录可实现开机时自动运行,简化了些服务脚本的过程。 -
/sbin/mingetty,X Display Manager(如果需要的话)
-
init在等待/etc/rc.d/rc执行完毕之后,将在指定的各个虚拟终端上运行/sbin/mingetty,等待用户的登录。 至此,Linux的启动完成
自定义服务脚本
#自定义服务脚本,使用 chkconfig 管理 [root@cent6]/etc/rc.d/init.d>cat testsrv #!/bin/bash #chkconfig:35 92 22 #默认启动runlevel 3 5 ,S92testsrv ,K22testsrv #description:test service in /etc/rc.d/init.d/ #放在/etc/rc.d/init.d/自动链接至 0 - 6 runlevel …… [ -x \$0 ]||chomd +x $0 #添加至服务列表 [root@cent6]~>chkconfig --add testsrt #从服务列表删除 [root@cent6]~>chkconfig --del testsrt #确认当前testsrv启动的runlevel [root@cent6]/etc/rc5.d>chkconfig --list testsrv testsrv 0:off 1:off 2:off 3:on 4:off 5:on 6:off #选择on的rc5.d/,此时有S92testsrv文件,并且是一个软链接 [root@cent6]/etc/rc5.d>ll S92testsrv lrwxrwxrwx. 1 root root 17 Aug 17 11:37 S92testsrv -> ../init.d/testsrv #修改S92 为预定义的 K22 文件,目的是看看runlevel5是否仍然 on [root@cent6]/etc/rc5.d>mv S92testsrv K22testsrv #runlevel5已经是off,说明chkconfig off 等于创建 K 开头的文件 [root@cent6]/etc/rc5.d>chkconfig --list testsrv testsrv 0:off 1:off 2:off 3:on 4:off 5:off 6:off #再次开启 runlevel5的testsrv服务 [root@cent6]/etc/rc5.d>chkconfig --level 5 testsrv on testsrv 0:off 1:off 2:off 3:on 4:off 5:on 6:off #rc5.d/目录下再次生成了S92testsrv文件 [root@cent6]/etc/rc5.d>ll S92testsrv lrwxrwxrwx. 1 root root 17 Aug 17 11:37 S92testsrv -> ../init.d/testsrv
-
Sysvinit 不仅需要负责初始化系统,还需要负责关闭系统。在系统关闭时,为了保证数据的一致性,需要小心地按顺序进行结束和清理工作。比如应该先停止对文件系统有读写操作的服务,然后再 umount 文件系统,否则数据就会丢失。这种顺序的控制这也是依靠/etc/rc.d/rc#.d/目录下所有脚本的命名规则来控制的,在该目录下所有以 K 开头的脚本都将在关闭系统时调用,字母 K 之后的数字定义了它们的执行顺序。这些脚本负责安全地停止服务或者其他的关闭工作。
Sysvinit 管理命令和控制功能
-
halt、init、killall、last、lastb、mesg、pidof、poweroff、reboot、shutdown、runlevel、sulogin、telinit、utmpdump、wall
Sysvinit 小结
-
sysvinit 的一个重要优点是确定的执行顺序:脚本严格按照启动数字的大小顺序执行,一个执行完毕再执行下一个,有利于错误排查
-
串行地执行脚本导致 sysvinit 运行效率较慢,此外动态设备加载等 Linux 新特性体现出 sysvinit 的一些问题
补充:守护进程
-
独立守护进程:就像上面的myservice一般能实现自我管理的守护进程
-
超级守护进程:xinetd服务,就像一个代理人,如管理telnet服务,虽然端口开着,但是服务没有被激活
-
瞬时守护进程:不需要关联至运行级别,以服务的方式被激活,由超级守护进程xinetd管理,可以认为这是Systemd的启动方式
Upstart
-
UpStart 主要的概念是 job 和 event。Job 就是一个工作单元,用来完成一件工作,比如启动一个后台服务,或者运行一个配置命令。每个 Job 都等待一个或多个事件,一旦事件发生,upstart 就触发该 job 完成相应的工作。UpStart 解决了之前提到的 sysvinit 的缺点。采用事件驱动模型
-
UpStart 可以:
更快地启动系统
当新硬件被发现时动态启动服务
硬件被拔除时动态停止服务 -
这些特点使得 UpStart 可以很好地应用在桌面或者便携式系统,处理这些系统中的动态硬件插拔特性。
-
原inittab下的记录
/etc/init/control-alt-delete.conf:快捷键重启的脚本,建议注释掉,防止误操作
/etc/init/tty.conf:重启终端脚本
/etc/init/start-ttys.conf:登录终端脚本
/etc/init/rc.conf:启动脚本
/etc/init/prefdm.conf:图像界面脚本
Systemd
-
CentOS 7 使用systemd替换了SysV。Systemd目的是要取代Unix时代以来一直在使用的init系统,兼容SysV和LSB的启动脚本,而且够在进程启动过程中更有效地引导加载服务
-
systemd的特性有:
支持并行化任务
同时采用socket式与D-Bus总线式激活服务;
按需启动守护进程(daemon);
利用 Linux 的 cgroups 监视进程;
支持快照和系统恢复;
维护挂载点和自动挂载点;
各服务间基于依赖关系进行精密控制。
原创文章,作者:helloc,如若转载,请注明出处:http://www.178linux.com/46234