本实验以centos6为例
系统启动流程说明
-->加载BIOS,通过BIOS程序加载CMOS的信息,并通过CMOS获得硬件信息
-->开机自检POST
-->读取MBR的信息
-->grub引导系统启动
-->开启系统第一个进程init
-->用户登陆
有几点我们需要理解:
1、MBR是磁盘的第一个扇区,512字节,其中前446字节是boot loader引导加载程序,后64字节是分区表,最后2字节是MBR的结束位55aa
系统要启动,就要加载内核、各种驱动,那linux的内核存放在/boot下,驱动文件存放在/lib/modules下,所以启动流程第一步得先进入/boot加载内核文件,
而/boot是一个单独的分区并使用ext4文件系统。也就是说要进入/boot加载内核得先有文件系统驱动,而要安装文件系统驱动得先加载内核。如此进入一个死循环。
但是我们知道,实际情况是linux可以正常启动的,这是什么原因呢?
因为有MBR,MBR中前446字节的boot loader起引导作用,我们称为grub stage1,接着进入stage1.5阶段,此阶段加载的信息在MBR512字节之后的27个扇区。
stage1.5结束后进入stage2阶段,stage2阶段会执行配置文件grub.conf,这份文件内容如下:
default=0 //默认加载的内核、initrd文件,0表示第一个title timeout=5 //开机过程中出现的菜单选项超时时间 splashimage=(hd0,0)/grub/splash.xpm.gz //启动菜单选项的背景图片 hiddenmenu //隐藏菜单的后台执行过程 title CentOS 6 (2.6.32-696.el6.x86_64) //名字而已 root (hd0,0) //以第1块磁盘的第1个分区为根,说白了就是/boot为根,此处的根为系统启动使用,与启动后的根/两码事 kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=UUID=f1d8d9f5-4d1a-42e8-8a7f-600f668ce44f rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet //kernel 以只读方式加载内核,此处的UUID是启动结束后的根/的UUID initrd /initramfs-2.6.32-696.el6.x86_64.img //initrd 其中含有文件系统驱动,这样就可以加载内核文件了
2、启动系统第一个进程/sbin/init,其作用就是部署好软件环境,即主机名称、网络配置、文件系统格式等
而实现这些功能,主要是由/etc/inittab和/etc/init.d/*.conf这些文件完成的(centos6版本)。centos5版本的这些功能全在/etcinittab这一个文件上。
其大致含义如下:
-->默认的runlevel,用户登陆系统默认的级别
- 0:关机
- 1:单用户模式
- 2:多用户模式,有些网络功能不支持
- 3:完全多用户模式,字符界面
- 4:预留
- 5:图形界面(默认runlevel)
- 6:重启
-->执行系统软件运行环境的脚本/etc/rc.d/rc.sysinit
其作用就是准备好系统的运行环境,如挂载文件系统、swap、时钟、加载外设驱动、激活sysctl.conf文件设置内核参数
-->7个不同runlevel,启动可非启动服务脚本的路径
-->断电和恢复供电的处理
-->终端tty的设置
-->界面运行设置
这些步骤完成了,用户就可以登陆使用系统了;
我们做个实验,加深下理解
准备:一块新的磁盘、一台装好系统的机器和一台没有系统的机器。可以在虚拟机上完成本实验
步骤1、在本机对新磁盘建分区、文件系统
创建2个必要的分区 /dev/sdb1对应boot,/dev/sdb2对应/
fdisk /dev/sdb
创建文件系统,以ext4为例
mkfs.ext4 /dev/sdb1 mkfs.ext4 /dev/sdb2
blkid 命令可以检查文件系统信息
步骤2、挂载boot
mkdir /mnt/boot 挂载目录必须为boot,因为grub的stage2会专门找到boot目录 mount /dev/sdb1 /mnt/boot/
步骤3、安装grub
grub-install --root-directory=/mnt /dev/sdb stage1安装在/dev/sdb磁盘上,stage2安装在/mnt/boot目录下
此时/mnt/boot里面会有用于grub的stage2阶段的目录
步骤4、复制内核、initramfs
cp /boot/vmlinuz-2.6.32-696.el6.x86_64 /mnt/boot/ cp /boot/initramfs-2.6.32-696.el6.x86_64.img /mnt/boot/
步骤5、编辑grub.conf
图中的内容上文基本都介绍过,本实验中root=/dev/sda2,因为这块磁盘是要作为另一台机器的启动磁盘自然是sdba2了
selinux=0,因为selinux可能会影响本实验效果,所以开始就将其关闭
init=/bin/bash,我们使用bash作为第一个启动进程
步骤6、挂载根/,并初始化
创建目录并挂载根
mkdir /mnt/root mount /dev/sdb2 /mnt/root/ mkdir /mnt/root/{etc,lib,sbin,tmp,var,sys,proc,dev,} //创建root下对应的目录
运行下述脚本,其作用是复制命令文件与库文件到根目录下(/mnt/root),前提是需要我们输入常用的命令
我们输入的命令就是自制的linux系统支持的命令
#! /bin/bash title () { export CMD read -t 30 -p "input an exec cmd or press ‘quit‘: " CMD if [ "$CMD" = "quit" ];then exit else is_exec fi title } #判断输入的是可执行文件 is_exec () { if `which $CMD &> /dev/null` ;then copy_cmdfile copy_libfile echo "--->done" else echo "not a command" exit fi } #拷贝命令文件 copy_cmdfile () { EXEC_CMD=`which $CMD` if [ ! -e /mnt/root$EXEC_CMD ];then cp --parents $EXEC_CMD /mnt/root fi unset EXEC_CMD } #拷贝命令文件对应的库文件 copy_libfile () { ldd `which $CMD` | grep -o "/.*[0-9] " | while read line ;do if [ ! -e /mnt/root$line ];then cp --parents $line /mnt/root/ fi done unset line } title
至此实验结束,然后关机,取出磁盘,装到另一台没有系统的主机上,启动即可
启动后的界面如下: