首先此篇先大体介绍下整个系统的开机流程,再来对其一一展开进行详细的说明
第一步:首先进行开机自检POST,确认硬件正常后进入下一步
第二步:BIOS initialization(BOOT SEQ)BIOS初始化,并按照BIOS中设定的开机启动加载设备进行依次的检测
第三步:MBR(bootloader)在BIOS检测到某一设备可以启动后,开始加载MBR上的引导程序,在linux中,引导分为2个阶段,首先加载在MBR上的一段极其精简的启动程序,由此启动程序引导boot目录中的grub,再由grub进行具体系统的引导启动(grub是一个很强大的系统启动引导管理软件,也可以引导window)
第三步:Kernel initialization 在由grub引导linux内核后,启动内核,由内核检测基本硬件设备装载对应驱动,并装载rootfs和启动init(/etc/inittab)
第四步:系统启动和初始化,在启动init后,才开始真正的系统启动,内核退居到后台,由init来接管整个系统的加载和启动,init会根据设定进行系统进一步的初始化,下面是init启动后进行的一系列操作
1.完成系统整体初始化:/etc/rc.d/rc.sysinit (此脚本可以细细研读)
2.启动对应级别的各个服务:/etc/rc.d/rc 利用/etc/rc.d/ec[0-6].d/目录下的所有脚本启动或者停止服务
/etc/rc.d/ec[0-6].d/下都是链接文件,链接到/etc/rc.d/init.d/下的各个脚本
3./etc/rc.local (链接到/etc/rc.d/rc.local)给用户定义的额外开机操作项
4.启动虚拟终端,验证用户登录(图形界面则调用其他如XDM来验证用户登录)
至此 系统启动完整,可以说,整个系统的启动都是靠一堆脚本来完成的
第一二步骤涉及到硬件的POST和BIOS阶段就不再细说了,从bootloader开始说起
bootloader
这是一段放置在MBR钱446字节中的一段精简的引导程序(MBR一共有512字节,后64字节既是分区表,还有最后2个字节的填充)
常见的bootloader程序有
LILO:LInux LOader 可以引导多个操作系统,但不支持大硬盘
GRUB:GRand Unified Bootloader 目前比较常见的引导加载器,这是一个分段的引导加载器,在Ubunt上用的是GRUB1.9x。
时隔10年,最新的GRUB2在昨天正式发布了,有兴趣的童鞋可以去关注下
可以在开机时进入GRUB的交互模式,直接输入参数启动系统,在这里可以输入单用户启动参数直接进入单用户模式进行密码修改等操作
之前说这是一个分段的引导程序这里来说说具体是怎么分段的
第一段:MBR
用来引导进入第二段,在完成第一段后,初始化GRUB自我初始化后,并正常启动第二段
第二段:/boot/grub
由于MBR上的引导程序只有446字节,所以能放置的内容很少,功能很弱,所以通过引导启动第二段放置在磁盘中/boot/grub目录下强大的GRUB程序,来扩展其更为强大的引导功能
此目录下的配置文件
/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 do not have a /boot partition. This means that
- # all kernel and initrd paths are relative to /, eg.
- # root (hd0,0)
- # kernel /boot/vmlinuz-version ro root=/dev/sda1
- # initrd /boot/initrd-[generic-]version.img
- #boot=/dev/sda
-
- #以上是注释说明
-
- #以下是全局设定
- default=0 #默认启动的系统顺序,从0开始数
- timeout=5 #等待用户选择系统的超时时间
-
- splashimage=(hd0,0)/boot/grub/splash.xpm.gz #开机图片的位置,这里的位置,由于GRUB是直接识别硬盘的,所以和在linux的树状文件系统要区分一下,如果在linux中boot挂载点是和单独分区,那么只要指向boot分区下的目录,不用从boot开始,直接写成splashimage=(hd0,0)/grub/splash.xpm.gz 我这里将boot和根放在同一分区,所以从boot目录开始写
-
- hiddenmenu #是否隐藏菜单
-
-
-
- #以下是各个引导系统的设定
- title CentOS (2.6.32-220.el6.i686) #菜单显示名称
-
- root (hd0,0) #内核所在分区
-
- kernel /boot/vmlinuz-2.6.32-220.el6.i686 ro root=UUID=f7ba45db-7d52-407e-996d-0d7c087f7a1a rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD quiet SYSFONT=latarcyrheb-sun16 rhgb crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM #内核所在位置和需要向内核传递的参数
-
- initrd /boot/initramfs-2.6.32-220.el6.i686.img #这是一个小linux,完整,精悍。 为了防止内核中没有根系统文件的驱动产生系统启动死循环(比如根是放在lvm设备中),先加载initrd这个精简的linux,然后内核借助这个精简的linux加载根文件系统的驱动,然后切换到真正的根文件系统继续进行系统加载
-
- password 123456 #启动此系统需要的密码,也可以放在全局设定中,表示在开机进入交互式GRUB编辑需要输入密码
Kernel initialization
1、硬件探测
2、硬件驱动初始化(initrd)
3、挂载根文件系统(为了避免额外进程写操作破坏文件系统,所以在这里是使用只读挂载)
4、启动/sbin/init (PID:1)
在Kernel阶段,需要挂在根目录,而linux单内核系统,但它也吸收了微内核的特性,所以它包括了内核模块。
内核:/boot/vmlinuz-version 模块:/libmodules/version/
把模块集成进内核能提高效率,但也增大了内核体积,所以使用加载模块的方式提高了可管理性
这里就造就了一个问题,由于内核比较精简,所以不可能集成进很多的驱动进去,由内核初始化后是必须要加载根文件系统的,一旦根文件系统放在RAID或LVM设备上,由于内核缺少这些高级文件系统的驱动,会导致无法加载。于是就在这里加了一层中间层,就是这里的initrd了。initrd是一个微型的根文件系统,内置额外内核中没有的驱动模块
首先内核借助initrd加载根文件系统,然后加载真实根文件系统驱动和其它必须驱动后,切换到真正的根文件系统。所以initrd只是起到一个过渡的作用
内核初始化产生的所有信息保存在/var/log/dmesg 二进制文件,使用dmesg命令查看
init 系统初始化
加载完成内核后,启动整个系统的父进程,PID为1 的init
init接管系统后,结合/etc/initab的配置,加载各种需要的库文件,启动各个进程,比如bash,用户登录验证等。。。
此篇写述说原理,具体打造过程请期待下一篇。 见 http://www.linuxidc.com/Linux/2012-07/64754.htm