深入探索linux系统的启动流程

1.启动流程总体介绍

第一. 按下主机电源后,BIOS做硬件检测并根据CMOS中记录,找到启动设备(一般为硬盘)。
第二, 接着BIOS 读取硬盘最前面的512个字节分区,也就是读取MBR区域的信息,并将linux loader装载到RAM中。接着系统的主控权就移交给Linux Loader来执行。
第三. 接着您就會看到一个开机选择画面,让你选择启动哪套操作系统。
第四. 选择 Linux OS 並按下 Enter 键以后,Linux Loader 就将 Linux kernel 载入内存,准备来进行其他初始化的工作。
第五. kernel 被成功载入后执行程序init,因此 init 的 PID 为 1。
第六. init 回去读取 /etc/inittab (initial table) 的內容,并执行该文件内的相关脚本scripts。
第七. 最后就是执行login 程序,此时会等待你输入账号密码,如果认证无误的话,就可以开启一个shell来使用了 !

其简单流程可用下图表示:

2. 低层次的系统启动

2.1 BIOS自检


   当电脑开机的时候,电脑会去读取存储在BIOS CMOS RAM(随机访问存储器)中 的BIOS设置,并进行开机自检(Power On Self Test:POST)。BIOS是烧录于主板上的EEPROM或flash存储设备中的程序,主要用来记忆外设及系统的相关设定,并提供一个图形界面来方便我们修改设定值。而你在BIOS中所做的设定,会被存放在CMOS RAM中,且这些数据不会因为您的关机而丢失,因为主板上的锂电池会负责供应CMOS RAM所需的电力 。
        BIOS的工作主要是侦测电脑的周边配套设备是否工作正常,如:(1)CPU的类型、速度、缓存等;(2)主板类型;(3)内存的速度,容量;(4)硬盘的大小,类型和工作模式;(5)风扇速度等。
      如果这些设备在开机的时候能够通过检测,说明电脑可以正常的工作。
      如果在POST阶段按下delete键,可以进入到BIOS设置的主界面,例如当你要调整开机顺序或修改日期时就可以这么做。接下来,BIOS将依照CMOS中所设定的开机顺序来依序查找启动设备,这个设备一般是硬盘。接着,进入到硬盘的MBR区域(引导扇区),也就是说,就会去读取硬盘的第0个磁柱的第0个磁头的第一个磁区(最前面 512 bytes 的磁区)。MBR 內主要是存放着BOOT partition Loader 和partition table,分别占据446 字节和64字节的空间。其中前446个字节中保存的BOOT partition Loader是一个选择启动分区,也就是电脑由那个硬盘分区来载入开机的程序。在这个446个字节的空间中保存的就是启动程序,然后由这个小程序来加载存储在其他位置的操作系统,也就是启动grub程序。
      partition table 是包含着四个分区的记录 (以 hda 来说为hda1 ~ hda4),比如起始、结束磁柱的信息及哪个 partition 有设定启动激活标志 (Active) 等,此时如果您硬盘上存在着两套 windows 的操作系统,那么MBR 上的BPL 就会根据 partition table 里设定为激活 Active 标记的的那个partition,而载入该 partition 的 boot sector,以完成后续的开机任务。至于 MBR 內剩下的 2 bytes 是存放检查码(Magic number),主要是让 BPL 去检查 MBR 区域的正确性。

 

  
2.2 载入启动程序

      BIOS自检完成后,进入到硬盘的MBR区域(引导扇区),第一阶段所用的boot loader(存放在引导扇区)被装载到RAM中并被执行。它的任务,就是加载第二阶段的boot loader。它它通过分析分区表,找出激活分区来完成这个任务,当它找到一个激活分区时,它将继续扫描剩下的分区表中的分区,以便确认他们都是未激活的。确认完毕后,激活分区的启动记录从设备中被读到RAM,并被执行。

       第二阶段的boot loader的任务就是加载linux内核,以及可选的初始化内存盘。把第一阶段和第二阶段的boot loaders联合起来,就是在x86个人电脑中,我们所说的linux loader(LILO)或者Grand Unified Bootloader(GRUB)。
   当负责第二阶段的boot loader位于内存中并被执行时,通常会显示一个一闪而过的屏幕,然后linux以及可选的初始化内存盘(initrd,一种临时的根文件系统)会被装载到存储器中。当系统镜像被加载时,第二阶段的boot loader将把控制权转交给内核镜像,与此同时,内核开始自解压并初始化。在这个阶段,第二阶段的boot loader会检查系统的硬件,枚举那些附加的硬件设备,挂载根设备,之后加载需要的内核模块。完成之后,第一个用户空间程序(init)开始执行,更高层次的系统初始化开始。

     

3. 高层次的系统启动流程

      内核加载完毕之后,创建若干内核线程(kernel thread),然后装入并执行程序/sbin/init(变成一个用户进程)。此时根文件系统/也已经被mount了。接下来init是系统第一个被执行的程序,所以它的进程号pid始终会是1,所有的其他程序进程都是由init负责产生的。
      此后,init根据/etc/inittab配置文件来执行相应的脚本进行系统初始化。这个文件负责设置init初始化程序初始化脚本在哪里;每个运行级初始化时运行的命令; 开机、关机、重启对应的命令;各运行级登陆时所运行的命令。
      对suse linux来说,执行的顺序为:


第一步,id:5:initdefault://  # 这里使用initdefault指定系统启动后进入的run-level
第二步,si::bootwait:/etc/rc.d/boot# 这里使用boot来指定系统初始化的脚本,也可以指定为其他脚本,如rc.sysinit.

其主要执行的工作大致如下:

(1). 挂载proc、sysfs、devpts 这一类的虚拟文件系统。
(2). 执行 /etc/init.d/boot.d 目录中的符号链接 (名称以S作开头) 所指向的 scripts,而这些 scripts 所要做的工作有:
 检查及挂载root文件系统、启用逻辑磁区、依 /etc/fstab 來检查及挂载本地端的文件系統 (root fs 除外)、载入模块、启动 swap、设定CMOS时间、设定 hostname 及 yp、储存核心信息于 /var/log/boot.msg、… 等等。
(3). 执行 /etc/init.d/boot.local 这支 script。当您有一些工作希望在关机过程被执行的话,可以在 boot.local 中做设定,比如模块的額外挂载及防火墙的设定。

第三步,执行每个run-level自己的初始化脚本

 

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
..........《中间省略N步,如第五、第六等等...............
init最后几步:根据run-level执行/etc/rc.d的脚本,执行/etc/rc.d/rc.local脚本,最后启动mingetty的虚拟控制台,等待用户登陆。
在/etc/rc.d/rcX.d内的脚本基本都是会调用/etc/rc.d/init.d内的脚本来启动或者停止服务。另外使用chkconfig也可以配置服务。chkconfig –list可以列出这些服务和预设的启动状态。
由于这里使用initdefault指定系统启动后进入的run-level为5,因此我们将转而执行/etc/rc.d/rc5.d/下的所有文件.我们看到这些文件的名称都是K或S开头的。
K代表的是Kill,而S代表的是Start。意思很简单,默认为开机要执行的服务,其文件名的开头就是S,若用户将某个服务关闭(不论是用哪一种工具程序),该文件名就会由S开头变为K开头。反之亦然,若将某服务关闭,则文件名便会是K开头。
      设置服务激活状态的另一个做法是将文件名的第一个字母直接由S变为K,或是将K变为S,这样开机默认激活状态就会从开启变为关闭,或是由关闭变为激活,是非常方便的一种做法。

Danny$ chkconfig gpm --list
gpm 0:off 1:off 2:on 3:off 4:on 5:0n 6:off
Danny$ mv s85gpm k85gpm
Danny$ chkconfig gpm --list
gpm 0:off 1:off 2:on 3:off 4:on 5:0ff6:off

 

        紧跟着英文字母后面的是一个两位数的数字,这个数字代表了执行的先后顺序,但请不要随意地更改数字,因为某些服务是有相关性的,若不小心将数字改掉,有可能会让某些服务无法正常被激活。

  当然这目录中的文件多寡和当初安装操作系统时所选择的项目有关,绝大部分都是服务程序,眼尖的读者应该也发现这些文件的颜色都是属于link文件的颜色。没错,在rcX.d目录中其实都是link,以link方式的做法弹性比较大,其中绝大部分的文件都是连接到/etc/rc.d/init.d/下的实体执行程序。

suselinux:~ #       ls -l /etc/init.d/rc5.d

lrwxrwxrwx 1 root root 6 Sep
6
00:11 K07xdm             -> ../xdm
lrwxrwxrwx 1 root root 7 Sep
6
00:11 K08cron ->              ../cron
lrwxrwxrwx 1 root root 9 Sep
6
00:11 K08hwscan             -> ../hwscan
lrwxrwxrwx 1 root root 7 Sep
6
00:11 K08nscd             -> ../nscd
lrwxrwxrwx 1 root root 9 Sep
6
00:12 K08xinetd             -> ../xinetd
lrwxrwxrwx 1 root root 7 Sep
6
00:11 K10sshd             -> ../sshd
lrwxrwxrwx 1 root root 6 Sep
6
00:11 K12nfs             -> ../nfs
lrwxrwxrwx 1 root root 8 Sep
6
00:11 K15smbfs             -> ../smbfs
lrwxrwxrwx 1 root root 9 Sep
6
00:11 K16syslog             -> ../syslog
lrwxrwxrwx 1 root root 10 Sep
6
00:11 K17network              -> ../network
lrwxrwxrwx 1 root root 10 Aug
29
20:35 S05network             -> ../network
lrwxrwxrwx 1 root root 9 Aug
29
18:37 S06syslog             -> ../syslog
lrwxrwxrwx 1 root root 8 Aug
29
18:44 S07smbfs              -> ../smbfs
lrwxrwxrwx 1 root root 6 Aug
29
18:41 S10nfs             -> ../nfs
lrwxrwxrwx 1 root root 7 Sep
6
00:11 S12sshd             -> ../sshd
lrwxrwxrwx 1 root root 7 Aug
29
18:45 S14cron ->             ../cron
lrwxrwxrwx 1 root root 9 Aug
29
18:41 S14hwscan             -> ../hwscan
lrwxrwxrwx 1 root root 7 Aug
29
18:45 S14nscd             -> ../nscd
lrwxrwxrwx 1 root root 9 Sep
6
00:12 S14xinetd             -> ../xinetd
lrwxrwxrwx 1 root root 6 Sep
6
00:11 S15xdm             -> ../xdm

 

 

附1:对运行级别的解释
0:halt, 1:单用户,2:多用户,3:多用户并启动NFS服务

  4:保留,5:运行xdm(X window)以图形界面方式登录 6:reboot

附2:

linux service命令             顾名思义,就是用于管理Linux操作系统中服务的命令。

1. 声明:这个命令不是在所有的linux发行版本中都有。主要是在redhat、fedora、mandriva和centos中。

2. 此命令位于/sbin目录下,用file命令查看此命令会发现它是一个脚本命令。

3. 分析脚本可知此命令的作用是去/etc/init.d目录下寻找相应的服务,进行开启和关闭等操作。

4. 开启httpd服务器:service httpd start

start可以换成restart表示重新启动,stop表示关闭,reload表示重新载入配置。

5. 关闭mysql服务器:service mysqld stop

6. 强烈建议大家将service命令替换为/etc/init.d/mysqld stop (因为有一些linux的版本不支持service)

 

 

 

你可能感兴趣的:(深入探索linux系统的启动流程)