当你按下计算机的电源按钮,你有没有想过其内部发生了什么奇奇怪怪的复杂的事情呢?
计算机的启动用英语说就是boot。这个词的来源也很有意思。在发明计算机的早期,工程师们有这么一个很矛盾的问题:要运行程序,就必须先启动计算机;但是要启动计算机,又要先运行程序。那时候要启动计算机真的是一件非常困难的事情。于是工程师们就用一句谚语来比喻计算机启动的过程:“Pull oneself up by one's bootstraps.”boot这个词就是从这里来的。
计算机启动分为四个阶段。
一、BIOS
上世纪七十年代初,只读存储器(read-only memory,即ROM)发明,开机程序被事先写入其中,计算机启动的第一件事情就是读取它里面的程序:BIOS(basic input/output system,即基本输入输出系统)。
1、硬件自检
BIOS首先检查计算机的各部分硬件能否满足基本的运行条件,这个过程称为硬件自检(power-on self-test,即POST)。如果不满足条件,主板会发出各种不同含义的蜂鸣,启动终止。如果硬件完好,屏幕就会显示CPU、内存、硬盘等信息。
2、启动顺序(boot sequence)
BIOS完成硬件自检以后,将会把控制权交给下一个启动程序。此时,BIOS会根据启动顺序寻找到下一阶段的启动程序。这里的启动顺序是事先设定好的,也就是将外部存储设备进行排序,BIOS就能知道到哪一个外部存储设备中去寻找了。
启动顺序是可以在BIOS中进行修改的。
二、主引导记录
BIOS按照启动顺序把控制权交给排在第一位的存储设备。
此时,计算机读取该设备的前512个字节,即其第一个扇区。如果这512个字节的最后两个字节是0X55和0XAA,那么就表示这个设备可以用于启动;否则,则把控制权转交给启动顺序中排在下一位的设备。
主引导记录(master boot record,MBR)就是存储设备的前512个字节的内容。
主引导记录是为了让计算机知道到哪里去找操作系统。它分为三个部分:1-446字节(调用操作系统的机器码)、447-510字节(分区表)、511-512字节(主引导记录签名,0X55和0XAA)。
分区表(partition table)就是将硬盘分成多个区。硬盘分区有许多好处。但每个分区都可能装有不同的操作系统,因此主引导记录中必须让计算机知道从哪个分区进行启动,然后将控制权转交给它。
分区表长度为64字节,其中又一分为四,各为16个字节。因此,一个硬盘只能存在最多四个一级分区,又称为主分区。每个主分区的16个字节又由以下各部分组成:
第1个字节:如果为0X80,就说明这个分区是激活的,控制权将会转交给它。(四个主分区中只能有一个是激活的)
第2-4个字节:主分区中第一个扇区的物理位置。(柱面、磁头、扇区号等)
第5个字节:主分区类型
第6-8个字节:主分区中最后一个扇区的物理位置。
第9-12个字节:主分区中第一个扇区的逻辑地址。
第13-16个字节:主分区的扇区总数。
主分区的扇区总数决定了这个主分区的长度,也就是说,一个主分区的扇区总数不能超过2的32次方。
若每个扇区为512字节,则单个分区不能大于2TB。又因为扇区的逻辑地址也只有32位,所以实际上单个硬盘的最大可利用空间也为2TB。如果想要使用更大的硬盘,则可以扩大扇区的字节数,或者增加扇区总数。
三、硬盘启动
现在,计算机的控制权在硬盘的某个分区下。
1、卷引导记录
计算机读取激活分区的第一个扇区,该扇区称为卷引导记录(volume boot record,VBR)。卷引导记录会告诉计算机操作系统在分区的那个位置,然后计算机就能够加载操作系统了。
2、扩展分区和逻辑分区
随着硬盘越来越大,四个主分区已经不够用了,但是分区表只有四项,所以规定,有且仅有一个分区可以被定义为扩展分区。
扩展分区中又可以被分为几个分区,这些分区就被称为逻辑分区。
如果操作系统是被装在逻辑分区中的,那么计算机就可能会通过以下方式加载操作系统。
计算机先读取扩展分区的第一个扇区(扩展引导记录,extended boot record,EBR),其中也包含一个64字节的分区表,但最多只有两项。计算机接着读取第二个逻辑分区的第一个扇区,再从里面找到第三个逻辑分区的位置,依此类推,直到分区表只有一项为止。也就是说,扩展分区中可以包含无数个逻辑分区。
但实际上,计算机很少通过这种方式加载装在扩展分区的操作系统,一般都会使用以下方式启动。
3、启动管理器
此时,计算机会读取主引导记录前446字节的机器码,但不会把控制权交给某个分区,而是运行启动管理器(boot loader),由用户自己来选择启动哪一个操作系统。
linux环境中,目前最流行的启动管理器是Grub。
四、操作系统
系统的控制权交给操作系统后,操作系统的内核首先被载入内存。
以linux系统为例,先载入/boot目录下的kernel。内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件(debian系统是/etc/initab)产生init进程。这是linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代。
然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登陆界面,等待输入用户名和密码。
至此计算机启动完成。