我们要成为某一方面的专家,就必须深知它的原理,知道它最基层的构架,这样我们才可以以不变应万变,Linux 也是一样,我们要想玩弄Linux股掌之中,就必须先知道它的基础,它是如何让启动的。

   下面就大致说一下启动的顺序:BIOS通电自检--主引导加载程序--内核初始化--系统初始化

   具体如下:
   主板通电--启动BIOS--加载BIOS硬件信息并自检--获取第一个设备启动号(MBR)--启动硬盘的主引导记录MBR--启动内核加载程序grub--加载内核并尝试驱动所有硬件设备(由initrd实现)--内核初始化完成,运行第一个程序init,init通过inittab的信息进行工作--运行/etc/rc.d/rc.sysinit进行系统初始化--启动内核模块(/etc/modprobe.comf)--init执行对应启动级别下的脚本(/erc/rc.d/rc*.d)--init执行/etc/rc.d/rc.local文件--执行/bin/login程序等待用户登录

上面的是不是看着有点不明白,没关系,先看一下下面的这些介绍,然后会有更详细的开机启动介绍。

   大家要搞清楚系统启动的过程,就必须知道每一步用到的文件和程序是用来做什么的,定义了什么。

BIOS是英文"Basic Input Output System"的缩略语,直译过来后中文名称就是"基本输入输出系统"。其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。

MBR:

每一个硬盘的第一个记录称为MBR。MBR 是英文Master Boot Record的缩写,中文意为主引导记录。硬盘的0磁道的第一个扇区就叫做MBR,它的大小是512字节,而这个区域可以分为两个部分。第一部分为pre- boot区(预启动区),占446字节,用于加载启动第二部分,第二部分是Partition table区(分区表),占64个字节(每16个字节标配一个分区,所以我们的硬盘只能有四个主分区,就在这里定义),该区相当于一个小程序,作用是判断哪个分区被标记为活动分区,然后去读取那个分区的启动区,并运行该区中的代码

为什么要使用在MBR中安装引导加载程序:操作核心必须要认识磁盘文件系统,才能读取里面的内容,但此时系统才刚开始启动,系统要如何认识文件系统呢?这时候就必须要有引导加载程序,才能加载内核。当前主流的grup引导加载程序可以支持Linux 和 Windows 的核心系统。

initrd:

首先我们要知道,系在加载内核的过程中,系统只会以只读方式载入根目录,所以为了系统启动的顺序进行,我们引入initrd概念。Linux 初始 RAM 磁盘(由initrd建立)是在系统引导过程中挂载的一个临时根文件系统,用来支持两阶段的引导过程。initrd 文件中包含了各种可执行程序和驱动程序,它们可以用来挂载实际的根文件系统,然后再将这个 initrd RAM 磁盘卸载,并释放内存。

关于rc*:init根据inittab文件定义的开机启动默认级别进入的相应系统级别,然后调用/etc/rc.d/rc根据级别参数执行相应级别目录/etc/rc.d/rc*.d/下的脚本

 

内核初始化过程的配置文件机器作用:/var/log/dmesg

1 硬件设备的探测

2 initrd文件,从中加载额外的设备驱动

3 以只读的方式挂载根文件系统

4 装载init进程 /sbin/init

 

系统的第一个进程init的配置文件及作用:/etc/inittab 

1 设定默认运行级别

2 启动系统初始化脚本

3 执行指定运行级别下的每一个启动脚本

4 设定CTRL+ALT+DEL组合键功能

5 设定该电源故障时执行的脚本

6 设定要启动的虚拟控制台/dev/tty[1-6]

7 设定当启动运行级别为5时做GUI初始化的脚本

 

我们看一下inittab文件里面的具体内容:

1: id:5:initdefault: 系统默认启动级别

2: si::sysinit:/etc/rc.d/rc.sysinit  执行系统初始化脚本

3: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  

 

使用rc脚本执行rc*.d目录内的脚本

目录/etc/rc*.d/中以S开头的表示进入该级别时要执行的脚本 K开头离开该级别时要关闭的脚本 这些脚本都为链接文件,真正的脚本位于/etc/init.d/下!

4:ca::ctrlaltdel:/sbin/shutdown -t3 -r now  设定CTRL+ALT+DEL组合键功能

5:pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"  电源故障处理

6:pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"  电源重新恢复关机取消处理

7:

1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6  标示6个虚拟控制台,respawn:用户退出时虚拟控制台关闭再开启等待用户下一次进入

8:x:5:respawn:/etc/X11/prefdm -nodaemon 启动图形界面等待用户登录

 

系统初始化脚本/etc/rc.d/rc.sysinit

1 激活udev和selinux

2 设置内核启动参数 /etc/sysctl.conf

3 设置系统时钟

4 装载键盘映射

5 启用交换分区 (虚拟内存)

6 设置主机名称 /etc/sysconfig/network

7 根文件系统自检并重新以读写方式挂载根文件系统

8 激活RAID和LVM设备

9 启动磁盘配额

10 检查ing挂载其他文件系统 /etc/fstab

11 清除不再使用锁和PID文件

 

大家看过上面的文件信息后,我再重述一遍linux的开机启动过程,希望能是大家的思路更加清晰:

开机通电后,BIOS进行自检,并且自己获得一个设备启动号,也就是将MBR定义为第一个要启动的设备,BIOS自检完成就将控制权交给MBR,MBR分为两部分,第一部分446字节,它的唯一作用就是引导第二部分,也就是我们常用的grub,grub通过其菜单功能和指向功能让我们选择需要加载的内核。通过引导加载程序读取内核文件(我们的内核文件一般放在/boot/vmlinuz-servion)后,机器会将内核解压到主存,然后通过内核功能来进行设备检测。在内核加载过程中,系统只会以只读方式载入根目录,为了让某些功能能以文件方式来读取,在系统启动时,就需要用initrd建立虚拟盘(RAM disk),所在grub利用引导加载功能加载核心是,也会加载进initrd的映像文件/boot/initrd-****.img,然后内核会自动以initrd来建立虚拟盘,并且用initrd-***.img文件内的linuxrc(笔者系统里的该程序名字为init)程序来加载模块,内核驱动外部硬件的工作完成,虚拟盘删除。核心加载完成后,系统准备就绪,执行第一个进程/sbin/init,通过id:5:initdefault: 设置系统默认启动级别,通过si::sysinit:/etc/rc.d/rc.sysinit  执行系统初始化脚本,通过l*:*:wait:/etc/rc.d/rc *  使用rc脚本执行rc*.d目录和rc.local目录内脚本。(Redhat中的运行模式2、3、5都把/etc/rc.d/rc.local做为初始化脚本中的最后一个

至此整个系统启动完成!

 

下面思考下:我们想要在开机时自动运行一个命令,该如何实现呢?以cvslockd命令为例

1:在/etc/rc.d/init.d/目录下

#vim cvslockd

#!/bin/bash

/usr/local/bin/cvslockd    命令的全路径

为脚本添加执行权限

#chmod +x /etc/rc.d/init.d/cvslockd

2:在文件/etc/inittab中查看系统的运行级别id:5:initdefault:,表示级别为5

 

3. 到/etc/rc.d/rc5.d目录下,把你要执行的可执行文件做一个软连接,而且在命名的时候要以大写S字母开头,S之后的数字大小代表执行顺序的先后,数字越大越后执行。

#ln -s /etc/rc.d/init.d/cvslockd /etc/rc5.d/S100cvslockd

#ln -s /etc/rc.d/init.d/cvslockd /etc/rc0.d/K20cvslockd

方法二:

在/etc/rc.d/rc.local 添加 exec /usr/local/bin/cvslockd

该方式是在最后启动cvslockd