Linux计算机上电后会发生什么?
Step1:BIOS(Basic Input Output System 基本输出输入系统)
BlOS是计算机上电后执行的第一个程序,作用是执行POST(Power on self test,上电自检),在发现问题时发出告警声,比如硬盘、显卡、声卡及各种接口等。然后在启动设备(cd-rom,网络,硬盘等)中搜寻boot loader,将boot loader stage1程序加载进内存,并执行。之后BIOS就隐于后台。
BIOS主要包括:
1. 自诊断程序(通过读取CMOSRAM中的内容,识别硬件配置,并对其进行自检和初始化)
2. CMOS设置程序(引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中)
3. 系统自检装载程序(在自检成功后,将磁盘0磁道0扇区上的引导程序装入内存,运行加载操作系统)
4. 主要I/O设备驱动程序和中断服务(BIOS和硬件直接打交道,需要加载I/O驱动程序)
Step2:MBR(Master Boot Record 硬盘主引导记录)
BIOS在硬件自检完成后,加载MBR到指定位置内存中并把控制权交给MBR。一般情况下,系统从硬盘启动,硬盘中存放boot loader stage1程序的扇区被称为MBR,即前512个字节,从而获取磁盘的分区信息和操作系统的存放位置。MBR是启动硬盘(/dev/sda)的首个扇区,告诉计算机从哪个分区来装载BootLoader,从而引导出操作系统。
MBR的组成:
第1-446字节:调用操作系统的机器码,是GRUB的关键引导程序
第447-510字节:硬盘分区表(Disk Partition table)
第511-512字节:主引导记录签名(0x55和0xAA)
分区表是将硬盘分为若干个区,长度为64字节,内部分为4项,每项16字节。一个硬盘最多只能分4个一级分区,又叫“主分区”。主分区的组成:
第1个字节:如果为0x80,就表示该主分区是装有操作系统的分区。
第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。
第5个字节:主分区类型。
第6-8个字节:主分区最后一个扇区的物理位置。
第9-12字节:该主分区第一个扇区的逻辑地址。
第13-16字节:主分区的扇区总数。
最后的四个字节(”主分区的扇区总数”),决定了这个主分区的长度。也就是说,一个主分区的扇区总数最多不超过2的32次方。
如果每个扇区为512个字节,就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位,所以单个硬盘可利用的空间最大也不超过2TB。如果想使用更大的硬盘,只有2个方法:一是提高每个扇区的字节数,二是增加扇区总数。
Step3:BootLoader(系统引导程序)和 GRUB
BootLoader是操作系统内核运行之前先运行的一段程序。计算机读取MBR前面446字节的机器码之后,运行事先安装的BootLoader,由用户选择启动哪一个操作系统。它负责完成系统硬件的初始化,比如时钟的设置、存储区映射、设置堆栈指针等,然后把操作系统内核从Flash区拷贝到RAM区,并跳转到内核的入口,将系统的控制权交给操作系统,此后机器运行的过程中与BootLoader再无关系。
Linux中,最流行的BootLoader是GRUB(GRandUnified Bootloader),对于GRUB而言,MBR的前446字节的引导程序属于GRUB的开始执行程序(stage1),当BIOS把MBR加载到内存后就把控制权交给GRUB,而后加载出GRUB的剩余代码,随后(stage1.5)将完成其它代码的加载和搬移以及文件系统初始化查找等工作,最终(stage2)把内核和initramfs文件(即initrd镜像)加载入内存中,然后把控制权交给内核。
Step4:Kernel 和 initrd
接下来kernel镜像被解压并执行,kernel完成初始化硬件、进程调度、内存管理等任务。
1、 解压缩Kernel并再次检测硬件,安装必要驱动
2、 初始化与文件系统相关的虚拟设备,LVM或RAID
3、 把initramfs文件(initrd,虚拟文件系统,包含一个最小linux系统)装载到根文件系统,挂在根目录下面
4、 执行initramfs(initrd)中的init进程(挂载真正的根文件系统),完成加载模块、检查磁盘fsck等任务
5、挂载真正的根文件系统之后执行/sbin/init程序
Kernel内核文件:
initramfs(initrd)文件:
Step5:/sbin/init
/sbin/init是Linux启动后第一个用户态下的进程(PID为1)。init读取的第一个文件是/etc/inittab,通过它init会确定我们Linux操作系统的运行级别。它会从文件/etc/fstab里查找分区表信息 然后做相应的挂载。然后init会启动/etc/init.d里指定的默认启动级别的所有服务/脚本。所有服务在这里通过init一个一个被初始化。在这 个过程里,init每次只启动一个服务,所有服务/守护进程都在后台执行并由init来管理。
以上提到的启动过程有一些不足的地方。而用一种更好的方式来替代传统init的需求已经存在很长时间了,也产生了许多替代方案。其中比较著名的有Upstart,Epoch,Muda和Systemd,其中Systemd获得最多关注并被认为是目前最佳的方案。
至此,全部启动过程完成。