控制权转交给内核后,内核重新检测各种硬件信息,(第一次为POST自检)我们前边说了,一个完整的Linux包括内核和内核之上的程序,因此内核还要加载提供这些程序功能的模块,然而这些模块都在根目录的/lib/modules/2.6.32-696.el6.x86_64下(/和/lib/modules/不能挂载不同的分区),这时候内核还没有文件系统的概念,没有文件系统就没办法挂载根目录,想要挂载根目录就需要相应的模块支持,而我们原本的问题就是如何加载模块(先有鸡后有蛋的问题)。
3.2 加载initrd
/boot/initramfs-2.6.32-696.el6.x86_64.img文件就是解决上面问题的,我们来看一下这个文件:
file initramfs-2.6.32-696.el6.x86_64.img # 查看该文件类型
cp initramfs-2.6.32-696.el6.x86_64.img /app
cd /app
mv initramfs-2.6.32-696.el6.x86_64.img initramfs-2.6.32-696.el6.x86_64.img.gz
# gzip解压文件必须以.gz后缀
gzip -d initramfs-2.6.32-696.el6.x86_64.img.gz
file initramfs-2.6.32-696.el6.x86_64.img
# 查看需要借助cpio命令
mkdir init
cd init
cpio -id < /app/initramfs-2.6.32-696.el6.x86_64.img
# 解压至/app/init目录下
我们发现解压之后的内容类似于真正/目录下内容,这是因为这是一个最小化的Linux根文件系统。内核就是先把这个文件展开,形成一个虚拟文件系统,内核借虚拟文件系统装载必要的模块,完成后释放该虚拟文件系统并挂载真正的根目录。
initrd的制作:
mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)
dracut /boot/initramfs-$(uname -r).img $(uname -r)
四、启动第一个进程init
4.1 init进程:主要功能是准备软件执行的环境
内核完成硬件检测和加载模块后,内核会呼叫第一个进程,就是/sbin/init,至此内核把控制权交给init进程
读取初始化配置文件/etc/inittab,决定操作系统的runlevel,/etc/inittab内有这样一句:
id:runlevel:action:process
id 代表设定的项目,没有具体的实际意义runlevel
执行级别,0-关机、1-单用户、2-没有NFS的多用户、
3-真正的多用户、4-预留、5-Xwindows、6-reboot
action init的动作行为,initdefault表示要默认启动的runlevel
process 执行动作的指令,一般为脚本文件
4.2 /etc/rc.d/rc.sysinit
读取/etc/rc.d/rc.sysinit系统初始化脚本,设置主机名,挂载/etc/fstab中的文件系统,修改/etc/sysctl.conf 的内核参数等各项系统环境。
查看该脚本内容,大致功能如下
定义主机名,如果不存在则将主机名定义为localhost;
读取/etc/sysconfig/network文件,设置网络环境;
挂载内存装置/proc和USB装置/sys,如果USB装置存在,则会加载usb模块并挂载usb文件系统;
接下来是SELINUX的一些相关设置;
设定text banner,显示欢迎界面;
...
将开机启动信息存放到/var/log/dmesg中。
4.3 /etc/rc.d/rc
执行/etc/rc.d/rc脚本,下面是/etc/rc.d/rc脚本中我们关心的代码部分:
# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do
# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/K??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
check_runlevel "$i" || continue
# Bring the subsystem down.
[ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
$i stop
[ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
done
# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do
# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] && continue
[ -f /var/lock/subsys/$subsys.init ] && continue
check_runlevel "$i" || continue