转自:http://cizixs.com/2015/01/18/linux-boot-process

简介

我们都知道:操作系统运行的代码是在硬盘上的,最终要跑到内存和 CPU 上,才能被我们使用。

那从摁下电源键到看到系统界面,操作系统是怎么霸占了所有的硬件资源,把自己加载到内存开始运行的呢? 可以想到有两个可能性:操作系统自己实现的,或者有其他贵人帮忙。如果是操作系统自己启动的,就有了一个“鸡生蛋,蛋生鸡”的问题;如果是后者的话,一定有在操作系统启动之前就能工作的神力,把沉睡在硬盘的操作系统变到工作状态。

事实上,Linux 系统的启动正是上面第二种情况。帮助把 Linux 内核(Kernel)加载到内存的程序是 Boot Loader,下图的箭头表示加载关系。

Boot Loader —-> Linux Kernel

现在只需要知道 Boot Loader 位于启动盘的第一个扇区,功能是引导 Linux 系统就可以啦,至于更详细的说明会在后面提到。那现在的问题是 Boot Loader 是怎么运行起来的?而且,系统怎么知道哪个可启动设备要使用呢?有时候计算机可能启动的设备可能有多个:网络、硬盘、U 盘,CD 盘等。这就需要另外一个东西来做这件事,那就是 BIOS。

BIOS —-> Boot Loader

顺着上面的思路,现在的问题是:BIOS 的谁启动的?呃,这好像是个没有止境的过程。不过幸运的是,难题就到此结束了。BIOS 是嵌在主板上的固件,计算机启动时候的约定就是启动 BIOS 开始执行。

最后总结一下 Linux 的启动过程:

  1. 摁下电源键,BIOS(Basic Input/Output System)启动初始化硬件的工作,包括屏幕和键盘,内存检测,这个过程也被成为 POST(Power On Self Test),然后按照 CMOS RAM 中设置的启动设备查找顺序,来寻找可启动设备 。注:BIOS 程序嵌在主板的 ROM 芯片上的。
  2. POST 过程结束后,系统的控制权从 BISO 转交到 boot loader。Boot loader 一般存储在系统的硬盘上(传统的 BIOS/MBR 系统),或者 EFI 分区上(最近的 EFI 系统)。这个时候机器不能获取外部的存储或者网络信息,一些重要的值(日期、时间、其他外部值)都是从 CMOS 里读取。CMOS 在计算机断电后也能工作的设备,Boot Loader 会在后面讲解。
  3. Boot Loader 选择要启动的操作系统,加载内核镜像和初始化 RAM disk 到内存。系统的内核开始运行,直到关机为止。

BIOS

摁下电源键的时候,计算机的一些寄存器被设置初值,指令寄存器 CS:IP 指向 BIOS 的第一条指令。BIOS 掌握控制权,来执行硬件检测的程序,BIOS 在结束自己生命之前会寻找可启动设备。那么,BIOS 怎么知道哪些设备室可以启动的呢?如果计算机要从一个不能启动的设置加载系统,会发生严重的错误。启动设备的第一个扇区的末尾两个字节一定是:0x55 和 0xAA,这两个魔法数就是区分可启动设备和不可启动设备的关键。使用sudo head -c 512 /dev/sda | hd 可以看到第一个扇区的内容,注意最后两个字符。

BIOS 如果找不到可启动设备的话,就会报No Bootable Device Error

Boot Loader

对于使用 BIOS/MBR 模式的系统来说,Boot Loader 位于硬盘的第一个扇区,也称为 MBR(Master Boot Record)。MBR 只有 512 字节,主要工作就是检查分区表,并找到可以启动的分区,一旦找到启动分区,就在该分区里找到后面的 Boot Loader – 比如GRUB,把它加载到内存(RAM)。

MBR 这么有限的字节空间里,主要包括了三部分的内容:

  1. bootstrap code:启动操作系统的代码
  2. 分区表:指示系统盘的位置
  3. 魔法数:0x55AA

对于使用 EFI/UEFI 模式的系统来说,UEFI 固件读取 Boot Manager 的数据来决定启动哪一个 UEFI 应用,已经找到它的位置。该固件然后启动 UEFI 应用,比如 GRUB。

现在的控制权都到了 GRUB 启动程序的手里,GRUB 根据你选择的系统(多系统的情况会有界面出现让用户选择,只有一个系统的情况会直接选择该系统),把系统的内核加载到内存开始运行,同时也会初始化 RAM disk 文件系统(initramfs)到内存,供内核使用,并把控制权交给内核。

Linux Kernel

内核一般都是压缩的,所以它的首要任务是解压缩,然后检查和分析系统的硬件并初始化内核里的硬件驱动程序。内核刚加载到内存的时候,文件系统还不能使用,它使用的是 Boot Loader 加载金内存的 initramfs。 内核被加载到内存后首要工作是:初始化和配置机器的内存、处理器、存储设备等,内核也会启动一些用户态的程序。

initramfs

 前面提到过 boot loader 加载到内存的 RAM disk,也就是 initramfs,现在就详细讲一讲它。initramfs 包含的一些程序和二进制文件,会执行一系列的动作,保证 root 文件系统 mount 到系统。这里动作包括,为需要的文件系统提供内核的功能,以及使用 udev(User Device) 工具来发现和加载硬盘的驱动程序。 等到 root 文件系统找到后,它会检查错误然后 mount 到系统。

mount 程序告诉操作系统某个文件系统可以使用,并把它加载到文件系统的某个路径(mount point)。如果这些动作都成功的话,initramfs 就会从内存中清除,init 程序(位于 /sbin/init)开始执行。

/sbin/init

init 处理挂载(mount)工作,是整个的文件系统正常运行的枢纽。需要注意的时,如果在访问存储设备的时候,需要的硬件驱动,必须在 initramfs 阶段都加载好。

到目前为止,内核程序准备好了所有的硬件资源,也把文件系统都挂载好了。它运行了 /sbin/init 程序,也就是第一个系统进程(之前运行的程序都不是 OS 级别的,不在 OS 的管辖范围),它的进程号(pid)就是 1。下面是我在自己的系统上运行 ps aux | grep init的结果,第二列就是进程号:

root         1  0.0  0.0  24320   864 ?        Ss   Jan15   0:00 /sbin/init

第一个启动的程序当然也肩负着比较重要的责任:把系统需要其他程序都启动起来。传统的 System V UNIX 工作模式下,这个过程是遍历 runlevels 序列的程序脚本,来启动或者停止预先定义的服务(service)。除了上面那个主要的任务外,init 也负责保持系统一直运行和在 shutdown 系统的清理工作,还有用户登入和登出的工作。

登陆和使用

前面已经说过了,init 程序负责用户的登入和登出。如果是服务器 linux 或者其他文本模式的 linux,init 就会启动 getty 程序来接受用户输入的用户名和密码来验证用户。

如果是图形界面的 linux, 会有 display manager 的服务负责检测显示屏和启动 X-server。display manager 也负责图形界面的用户登陆,以及启动正确的桌面环境。

参考资料

  1. edx 上 introduction to linux 的启动章节
  2. 阮一峰介绍计算机启动的文章
  3. wikipedia 上相关文章

【转载】Linux启动过程的更多相关文章

  1. [转载] Linux启动过程详解-《别怕Linux编程》之八

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket.为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. = ...

  2. (转载)Linux启动过程详解

    启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘 ...

  3. 深入理解Linux启动过程

    深入理解Linux启动过程       本文详细分析了Linux桌面操作系统的启动过程,涉及到BIOS系统.LILO 和GRUB引导装载程序,以及bootsect.setup.vmlinux等映像文件 ...

  4. Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)

    启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬 ...

  5. Linux启动过程详解

    Linux启动过程详解 附上两张图,加深记忆 图1: 图2: 第一张图比较简洁明了,下面对第一张图的步骤进行详解: 加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的 ...

  6. 嵌入式Linux启动过程中的问题积累

    嵌入式Linux启动过程中的问题积累 Dongas 07-12-19 1.Bad Magic Number ## Booting image at 33000000 ... Bad Magic Num ...

  7. [linux 整理] linux启动过程3

    本文介绍linux启动过程的第三步 busybox--------------------> rc init busybox位置即内容 busybox/init/init.c 1.各种设置信号 ...

  8. 从Linux启动过程到android启动过程

    Linux启动过程: 1.首先开机给系统供电,此时硬件电路会产生一个确定的复位时序,保证cpu是最后一个被复位的器件.为什么cpu要最后被复位呢?因为 如果cpu第一个被复位,则当cpu复位后开始运行 ...

  9. Linux启动过程简述

    Linux启动过程: 图片来自:https://www.cnblogs.com/codecc/p/boot.html 简单来讲: 加载BIOS–>读取MBR–>Boot Loader–&g ...

  10. Linux 启动过程详解

    目录 1. Linux启动过程 2. 启动过程概述 3. 引导加载阶段 4. 内核阶段 4.1 内核加载阶段 4.2 内核启动阶段 5. 早期的用户空间 6. 初始化过程 6.1 SysV init ...

随机推荐

  1. C#读取网络流,读取网络上的js文件

    写博客的目的就是让其他人少走弯路. C#读取网络上的流和js文件出现的问题 一开始看了今天博客园上的推荐文章,用C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子),然 ...

  2. Vue学习笔记-1

    前言 本文不是Vue.js的教程,只是一边看官网Vue的教程文档一边记录并总结学习过程中遇到的一些问题和思考的笔记. 1.vue和avalon一样,都不支持VM初始时不存在的属性 而在Angular里 ...

  3. 【python游戏编程之旅】第八篇---pygame游戏开发常用数据结构

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中冲突检测技术:http://www.cnblogs.com/msxh/ ...

  4. 如何快速从一个Storage Account拷贝到另一个账号

    当您有两个Storage Account的时候,怎样快速做到从一个账号拷贝到另一个账号呢.当拷贝的文件比较,例如100多G(VHD文件). http://code.msdn.microsoft.com ...

  5. WebHeaderCollection 类

    https://msdn.microsoft.com/zh-cn/library/system.net.webheadercollection(v=VS.95).aspx /// <summar ...

  6. [BZOJ1924][Sdoi2010]所托门王的宝藏(缩点+DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1924 分析: 首先把传送门作为点建图 这个数据很弱的,没有那种卡你的. 把每行的情况存 ...

  7. fir2(n,f,m)

    编辑 函数fir2用来设计多通带任意响应FIR滤波器,该滤波器的幅频特性由向量对f和m确定,f为归一化频率向量,m为对应频率点上的幅度.当设计的滤波器在频率为π的幅度响应不是0时,滤波器的阶数n为偶数

  8. LeetCode Weekly Contest 8

    LeetCode Weekly Contest 8 415. Add Strings User Accepted: 765 User Tried: 822 Total Accepted: 789 To ...

  9. [转]7个高性能JavaScript代码高亮插件

    对于喜欢写技术博客的同学来说,一定对代码高亮组件非常熟悉.一款优秀的JavaScript代码高亮插件,将会帮助你渲染任何一种编程语言,包括一些关键字的着色,以及每行代码的缩进等.今天我们要来分享一些高 ...

  10. Java 接口中常量的思考

    接口中不允许方法的实现,而抽象类是允许方法实现的及定义变量的,因此我们可以看出接口是比抽象类更高层次的抽象.如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为(例如set()方法 ...