Linux操作系统启动过程详解

 如果你对Linux操作系统有一定的了解,想对其更深层次的东西做进一步探究。这当中就包括系统的启动流程、文件系统的组成结构、基于动态库和静态库的程序在执行时的异同、协议栈的架构和原理、驱动程序的机制等等。

  其中Linux操作系统启动过程肯定是大家最有兴趣了解的,这里在综合了现有网上大家智慧的基础上,基于2.6.32的内核的CentOS 6.0系统,对Linux的启动流程做了些分析,希望对大家有所帮助。

  OK,我们言归正传。对于一台安装了Linux系统的主机来说,当用户按下开机按钮时,一共要经历以下几个过程,如图:

  其中,每个过程都执行了自己该做的初始化部分的事情,有些过程又可分为好几个子过程。接下来,我们就对每个阶段做一个详细分析和讲解。

  一、BIOS自检

  稍有计算机基础的人都应该听过BIOS(Basic Input / Output System),又称基本输入输出系统,可以视为是一个永久地记录在ROM中的一个软件,是操作系统输入输出管理系统的一部分。早期的BIOS芯片确实是”只读”的,里面的内容是用一种烧录器写入的,一旦写入就不能更改,除非更换芯片。现在的主机板都使用一种叫Flash EPROM的芯片来存储系统BIOS,里面的内容可通过使用主板厂商提供的擦写程序擦除后重新写入,这样就给用户升级BIOS提供了极大的方便。

  BIOS的功能由两部分组成,分别是POST码和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动。BIOS两个阶段所做的详细工作如下:

  步骤1:上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;

  步骤2:步骤1成功后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。

  至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。

  PS:在个人电脑中,Linux的启动是从0xFFFF0地址开始的。

  如果你对Linux操作系统有一定的了解,想对其更深层次的东西做进一步探究。这当中就包括系统的启动流程、文件系统的组成结构、基于动态库和静态库的程序在执行时的异同、协议栈的架构和原理、驱动程序的机制等等。

  其中Linux操作系统启动过程肯定是大家最有兴趣了解的,这里在综合了现有网上大家智慧的基础上,基于2.6.32的内核的CentOS 6.0系统,对Linux的启动流程做了些分析,希望对大家有所帮助。

  OK,我们言归正传。对于一台安装了Linux系统的主机来说,当用户按下开机按钮时,一共要经历以下几个过程,如图:

  其中,每个过程都执行了自己该做的初始化部分的事情,有些过程又可分为好几个子过程。接下来,我们就对每个阶段做一个详细分析和讲解。

  一、BIOS自检

  稍有计算机基础的人都应该听过BIOS(Basic Input / Output System),又称基本输入输出系统,可以视为是一个永久地记录在ROM中的一个软件,是操作系统输入输出管理系统的一部分。早期的BIOS芯片确实是”只读”的,里面的内容是用一种烧录器写入的,一旦写入就不能更改,除非更换芯片。现在的主机板都使用一种叫Flash EPROM的芯片来存储系统BIOS,里面的内容可通过使用主板厂商提供的擦写程序擦除后重新写入,这样就给用户升级BIOS提供了极大的方便。

  BIOS的功能由两部分组成,分别是POST码和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动。BIOS两个阶段所做的详细工作如下:

  步骤1:上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;

  步骤2:步骤1成功后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。

  至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。

  PS:在个人电脑中,Linux的启动是从0xFFFF0地址开始的。

另外一个概念:initramfs

  initramfs 是在 kernel 2.5中引入的技术,实际上它的含义就是:在内核镜像中附加一个cpio包,这个cpio包中包含了一个小型的文件系统,当内核启动时,内核将这个 cpio包解开,并且将其中包含的文件系统释放到rootfs中,内核中的一部分初始化代码会放到这个文件系统中,作为用户层进程来执行。这样带来的明显的好处是精简了内核的初始化代码,而且使得内核的初始化过程更容易定制。

  疑惑的是:我的内核是2.6.32-71.el6.i686版本,但在我的/boot分区下面却存在的是/boot/initramfs-2.6.32-71.el6.i686.img类型的文件,没搞明白,还望高人解惑。我只知道在2.6内核中支持两种格式的initrd,一种是2.4内核的文件系统镜像image-initrd,一种是cpio格式。接下来我们就来探究一下initramfs-2.6.32-71.el6.i686.img里到底放了那些东西。

  在tmp文件夹中解压initrd.img里的内容:

  如果initrd.img文件的格式显示为“initrd.img:ISO 9660 CD-ROM filesystem data”,则可直接输入命令“mount -o loop initrd.img /mnt/test”进行挂载。

  通过上的分析和我们的验证,我们确实得到了这样的结论:

  grub的stage2将initrd加载到内存里,让后将其中的内容释放到内容中,内核便去执行initrd中的init脚本,这时内核将控制权交给了init文件处理。我们简单浏览一下init脚本的内容,发现它也主要是加载各种存储介质相关的设备驱动程序。当所需的驱动程序加载完后,会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载。这一步结束后,释放未使用的内存,转换到真正的根文件系统上面去,同时运行/sbin/init程序,执行系统的1号进程。此后系统的控制权就全权交给/sbin/init进程了。

  四、初始化系统

  经过千辛万苦的跋涉,我们终于接近黎明的曙光了。接下来就是最后一步了:初始化系统。/sbin/init进程是系统其他所有进程的父进程,当它接管了系统的控制权先之后,它首先会去读取/etc/inittab文件来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等。主要包括以下工作:

  1. 执行系统初始化脚本(/etc/rc.d/rc.sysinit),对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,到此系统算是基本运行起来了,后面需要进行运行级别的确定及相应服务的启动。rc.sysinit所做的事情(不同的Linux发行版,该文件可能有些差异)如下:

  (1)获取网络环境与主机类型。首先会读取网络环境设置文件”/etc/sysconfig/network”,获取主机名称与默认网关等网络环境。

  (2)测试与载入内存设备/proc及usb设备/sys。除了/proc外,系统会主动检测是否有usb设备,并主动加载usb驱动,尝试载入usb文件系统。

  (3)决定是否启动SELinux。

  (4)接口设备的检测与即插即用(pnp)参数的测试。

  (5)用户自定义模块的加载。用户可以再”/etc/sysconfig/modules/*.modules”加入自定义的模块,此时会加载到系统中。

  (6)加载核心的相关设置。按”/etc/sysctl.conf”这个文件的设置值配置功能。

  (7)设置系统时间(clock)。

  (8)设置终端的控制台的字形。

  (9)设置raid及LVM等硬盘功能。

  (10)以方式查看检验磁盘文件系统。

  (11)进行磁盘配额quota的转换。

  (12)重新以读取模式载入系统磁盘。

  (13)启动quota功能。

  (14)启动系统随机数设备(产生随机数功能)。

  (15)清楚启动过程中的临时文件。

  (16)将启动信息加载到”/var/log/dmesg”文件中。

  当/etc/rc.d/rc.sysinit执行完后,系统就可以顺利工作了,只是还需要启动系统所需要的各种服务,这样主机才可以提供相关的网络和主机功能,因此便会执行下面的脚本。

  2. 执行/etc/rc.d/rc脚本。该文件定义了服务启动的顺序是先K后S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rc*.d(*=0~6)目录下,所有的文件均是指向/etc/init.d下相应文件的符号链接。rc.sysinit通过分析/etc/inittab文件来确定系统的启动级别,然后才去执行/etc/rc.d/rc*.d下的文件。

  /etc/init.d-> /etc/rc.d/init.d

  /etc/rc ->/etc/rc.d/rc

  /etc/rc*.d ->/etc/rc.d/rc*.d

  /etc/rc.local-> /etc/rc.d/rc.local

  /etc/rc.sysinit-> /etc/rc.d/rc.sysinit

  也就是说,/etc目录下的init.d、rc、rc*.d、rc.local和rc.sysinit均是指向/etc/rc.d目录下相应文件和文件夹的符号链接。我们以启动级别3为例来简要说明一下。

  /etc/rc.d/rc3.d目录,该目录下的内容全部都是以 S 或 K 开头的链接文件,都链接到”/etc/rc.d/init.d”目录下的各种shell脚本。S表示的是启动时需要start的服务内容,K表示关机时需要关闭的服务内容。/etc/rc.d/rc*.d中的系统服务会在系统后台启动,如果要对某个运行级别中的服务进行更具体的定制,通过chkconfig命令来操作,或者通过setup、ntsys、system-config-services来进行定制。如果我们需要自己增加启动的内容,可以在init.d目录中增加相关的shell脚本,然后在rc*.d目录中建立链接文件指向该shell脚本。这些shell脚本的启动或结束顺序是由S或K字母后面的数字决定,数字越小的脚本越先执行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先执行。  3. 执行用户自定义引导程序/etc/rc.d/rc.local。其实当执行/etc/rc.d/rc3.d/S99local时,它就是在执行/etc/rc.d/rc.local。S99local是指向rc.local的符号链接。就是一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。

  4. 完成了系统所有的启动任务后,linux会启动终端或X-Window来等待用户登录。tty1,tty2,tty3…这表示在运行等级1,2,3,4的时候,都会执行”/sbin/mingetty”,而且执行了6个,所以linux会有6个纯文本终端,mingetty就是启动终端的命令。

  除了这6个之外还会执行”/etc/X11/prefdm-nodaemon”这个主要启动X-Window

  至此,系统就启动完毕了。

  PS: 最后附上一张非常完整的系统启动流程图,适合各个水平阶段的读者。

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-08-04 10:33:46

Linux操作系统启动过程详解的相关文章

Linux操作系统内核编译详解_unix linux

    内核简介 内核,是一个操作系统的核心.它负责管理系统的进程.内存.设备驱动程序.文件和网络系统,决定着系统的性能和稳定性.   Linux的一个重要的特点就是其源代码的公开性,所有的内核源程序都可以在/usr/src/linux下找到,大部分应用软件也都是遵循GPL而设计的,你都可以获取相应的源程序代码.全世界任何一个软件工程师都可以将自己认为优秀的代码加入到其中,由此引发的一个明显的好处就是Linux修补漏洞的快速以及对最新软件技术的利用.而Linux的内核则是这些特点的最直接

linux系统启动过程详解-开机加电后发生了什么 --linux内核剖析(零)

linux系统的启动流程 关于linux系统的启动流程我们可以按步进行划分为如下: BIOS POST自检 BIOS(Boot Sequence) 引导操作系统 加载对应引导上的MBR(bootloader) 主引导设置加载其BootLoader 加载操作系统 启动BIOS,准备实模式下的中断向量表和中断服务程序 电脑启动后,CPU逻辑电路被设计为只能运行内存中的程序,没有能力直接运行存在于软盘或硬盘中的操作系统,如果想要运行,必须要加载到内存(RAM)中. BIOS是如何启动的,CPU硬件逻辑

《嵌入式 Linux应用程序开发标准教程(第2版)》——2.2 Linux启动过程详解

2.2 Linux启动过程详解 嵌入式 Linux应用程序开发标准教程(第2版) 在了解了Linux的常见命令之后,下面详细讲解Linux的启动过程.Linux的启动过程包含了Linux工作原理的精髓,而且在嵌入式开发过程中非常需要这方面的知识. 2.2.1 概述 用户开机启动Linux过程如下: (1)当用户打开PC(intel CPU)的电源时,CPU将自动进入实模式,并从地址0xFFFF0000开始自动执行程序代码,这个地址通常是ROM-BIOS中的地址.这时BIOS进行开机自检,并按BI

DBA_Oracle Startup / Shutdown启动和关闭过程详解(概念)(对数据库进行各种维护操作)_oracle

一.摘要 Oracle数据库的完整启动过程是分步骤完成的,包含以下3个步骤: 启动实例-->加载数据库-->打开数据库 因为Oracle数据库启动过程中不同的阶段可以对数据库进行不同的维护操作,对应我们不同的需求,所以就需不同的模式启动数据库. 1. Oracle启动需要经历四个状态:SHUTDOWN .NOMOUNT .MOUNT .OPEN 2. Oracle关闭的四种方式:Normal, Immediate, Transactional, Abort 3. 启动和关闭过程详解   二.数

linux中了minerd之后的完全清理过程(详解)_Linux

一不小心装了一个Redis服务,开了一个全网的默认端口,一开始以为这台服务器没有公网ip,结果发现之后悔之莫及啊 某天发现cpu load高的出奇,发现一个minerd进程 占了大量cpu,google了一下,发现自己中招了 下面就是清理过程 第一步 1.立即停止redis服务,修改端口权限,增加密码措施 2.按照网上的资料 删除 crontab 里的两个内容 sudo rm /var/spool/cron/root sudo rm /var/spool/cron/crontabs/root 3

《Linux 设备驱动开发详解(第2版)》——1.6 设备驱动Hello World:LED驱动

1.6 设备驱动Hello World:LED驱动 Linux 设备驱动开发详解(第2版)1.6.1 无操作系统时的LED驱动 在嵌入式系统的设计中,LED一般直接由CPU的GPIO(通用可编程I/O口)控制.GPIO一般由两组寄存器控制,即一组控制寄存器和一组数据寄存器.控制寄存器可设置GPIO口的工作方式为输入或是输出.当引脚被设置为输出时,向数据寄存器的对应位写入1和0会分别在引脚上产生高电平和低电平:当引脚设置为输入时,读取数据寄存器的对应位可获得引脚上的电平为高或低. 在本例子中,我们

Linux下chkconfig命令详解(转)

Linux下chkconfig命令详解 chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--add][--del][--list][系统服务] 或 chkconfig [--level <等级代号>][系统服务][on/off/reset] chkconfig在没有参数运行时,显示用法.如果加上服务名,那么就检查这个服务是否在当前运行级启动.如果是,返

Win 2000系统引导过程详解(6)

过程|详解 Boot.ini文件包括[boot loader].[operating systems]两个部分,[boot loader]包括等待时间和默认引导系统两个参数,timeout后边的数字表示等待的秒数,default后边的是默认引导系统的位置.[operating systems]则包括安装的所有系统的ARC(Advanced RISC Computing)引导路径(等于号之前的部分)和他们在菜单上显示出的名字(引号之间的文本),以及启动参数(斜杠后边的部分).下边的表三将详细向您解

.NET配置文件解析过程详解

过程|详解 在我看来,WEB project的开发与WINFORM的开发最大的区别在于web的运行是在Framework上更高一层框架上运行,即ASP.NET框架,程序员在web下的开发可以说是黑盒开发,不是让你去定义程序入口和执行顺序,而是asp.net来调用你的各个方法,程序员做的一切都是一种受控的舞蹈.就像我们调用nunit之类的工具来测试一个dll一样,nunit是容器,是框架,执行哪个方法是由nunt来决定的.因此,也就有了页面执行周期各状态等令刚入门的程序员困惑不已的事,其实,究其根