计算机是怎样启动的?

摘要:
整个计算机启动过程分为四个阶段。其中一项是“设置启动顺序”。计算机读取设备的第一个扇区。然后将控制转移到“启动序列”中的下一个设备。这是Linux启动后的第一个过程。因为在BIOS阶段,计算机的行为基本上是写死的。

从打开电源到開始操作。计算机的启动是一个很复杂的过程。

计算机是怎样启动的?第1张

我一直搞不清楚,这个过程究竟是怎么回事。仅仅看见屏幕高速滚动各种提示...... 这几天,我查了一些资料。试图搞懂它。以下就是我整理的笔记。

零、boot的含义

先问一个问题。"启动"用英语怎么说?

回答是boot。但是,boot原来的意思是靴子,"启动"与靴子有什么关系呢? 原来,这里的boot是bootstrap(鞋带)的缩写,它来自一句谚语:

  "pull oneself up by one's bootstraps"

字面意思是"拽着鞋带把自己拉起来",这当然是不可能的事情。最早的时候。project师们用它来比喻,计算机启动是一个非常矛盾的过程:必须先执行程序,然后计算机才干启动,可是计算机不启动就无法执行程序!

早期真的是这样,必须想尽各种办法,把一小段程序装进内存,然后计算机才干正常执行。所以,project师们把这个过程叫做"拉鞋带",久而久之就简称为boot了。

计算机的整个启动过程分成四个阶段。

一、第一阶段:BIOS

上个世纪70年代初,"仅仅读内存"(read-only memory,缩写为ROM)发明。开机程序被刷入ROM芯片。计算机通电后,第一件事就是读取它。

计算机是怎样启动的?第2张

这块芯片里的程序叫做"基本輸出輸入系統"(Basic Input/Output System)。简称为BIOS

1.1 硬件自检

BIOS程序首先检查,计算机硬件是否能满足执行的基本条件。这叫做"硬件自检"(Power-On Self-Test),缩写为POST

假设硬件出现故障。主板会发出不同含义的蜂鸣,启动中止。

假设没有问题,屏幕就会显示出CPU、内存、硬盘等信息。

计算机是怎样启动的?第3张

1.2 启动顺序

硬件自检完毕后。BIOS把控制权转交给下一阶段的启动程序。

这时,BIOS须要知道,"下一阶段的启动程序"详细存放在哪一个设备。也就是说,BIOS须要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。

这样的排序叫做"启动顺序"(Boot Sequence)。

打开BIOS的操作界面。里面有一项就是"设定启动顺序"。

计算机是怎样启动的?第4张

二、第二阶段:主引导记录

BIOS依照"启动顺序",把控制权转交给排在第一位的储存设备。

这时。计算机读取该设备的第一个扇区。也就是读取最前面的512个字节。假设这512个字节的最后两个字节是0x55和0xAA,表明这个设备能够用于启动;假设不是,表明设备不能用于启动。控制权于是被转交给"启动顺序"中的下一个设备。

这最前面的512个字节,就叫做"主引导记录"(Master boot record,缩写为MBR)。

2.1 主引导记录的结构

"主引导记录"仅仅有512个字节。放不了太多东西。它的主要作用是,告诉计算机到硬盘的哪一个位置去找操作系统。

主引导记录由三个部分组成:

  (1) 第1-446字节:调用操作系统的机器码。

  (2) 第447-510字节:分区表(Partition table)。

  (3) 第511-512字节:主引导记录签名(0x55和0xAA)。

当中,第二部分"分区表"的作用,是将硬盘分成若干个区。

2.2 分区表

硬盘分区有非常多优点。考虑到每一个区能够安装不同的操作系统。"主引导记录"因此必须知道将控制权转交给哪个区。

分区表的长度仅仅有64个字节,里面又分成四项。每项16个字节。所以,一个硬盘最多仅仅能分四个一级分区,又叫做"主分区"。

每一个主分区的16个字节,由6个部分组成:

  (1) 第1个字节:假设为0x80。就表示该主分区是激活分区。控制权要转交给这个分区。

四个主分区里面仅仅能有一个是激活的。

  (2) 第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。

  (3) 第5个字节:主分区类型

  (4) 第6-8个字节:主分区最后一个扇区的物理位置。

  (5) 第9-12字节:该主分区第一个扇区的逻辑地址。

  (6) 第13-16字节:主分区的扇区总数。

最后的四个字节("主分区的扇区总数"),决定了这个主分区的长度。

也就是说。一个主分区的扇区总数最多不超过2的32次方。

假设每一个扇区为512个字节,就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位,所以单个硬盘可利用的空间最大也不超过2TB。

假设想使用更大的硬盘,仅仅有2个方法:一是提高每一个扇区的字节数。二是添加扇区总数

三、第三阶段:硬盘启动

这时,计算机的控制权就要转交给硬盘的某个分区了,这里又分成三种情况。

3.1 情况A:卷引导记录

上一节提到。四个主分区里面。仅仅有一个是激活的。计算机会读取激活分区的第一个扇区,叫做"卷引导记录"(Volume boot record,缩写为VBR)。

"卷引导记录"的主要作用是,告诉计算机,操作系统在这个分区里的位置。

然后,计算机就会载入操作系统了。

3.2 情况B:扩展分区和逻辑分区

随着硬盘越来越大,四个主分区已经不够了,须要很多其它的分区。可是,分区表仅仅有四项,因此规定有且仅有一个区能够被定义成"扩展分区"(Extended partition)。

所谓"扩展分区"。就是指这个区里面又分成多个区。

这样的分区里面的分区。就叫做"逻辑分区"(logical partition)。

计算机先读取扩展分区的第一个扇区。叫做"扩展引导记录"(Extended boot record,缩写为EBR)。

它里面也包括一张64字节的分区表。可是最多仅仅有两项(也就是两个逻辑分区)。

计算机接着读取第二个逻辑分区的第一个扇区。再从里面的分区表中找到第三个逻辑分区的位置,以此类推,直到某个逻辑分区的分区表仅仅包括它自身为止(即仅仅有一个分区项)。因此,扩展分区能够包括无数个逻辑分区。

可是。似乎非常少通过这样的方式启动操作系统。

假设操作系统确实安装在扩展分区,一般採用下一种方式启动。

3.3 情况C:启动管理器

在这样的情况下,计算机读取"主引导记录"前面446字节的机器码之后,不再把控制权转交给某一个分区,而是执行事先安装的"启动管理器"(boot loader),由用户选择启动哪一个操作系统。

Linux环境中,眼下最流行的启动管理器是Grub

计算机是怎样启动的?第5张

四、第四阶段:操作系统

控制权转交给操作系统后,操作系统的内核首先被加载内存。

以Linux系统为例,先载入/boot文件夹以下的kernel。内核载入成功后,第一个执行的程序是/sbin/init。

它依据配置文件(Debian系统是/etc/initab)产生init进程。这是Linux启动后的第一个进程。pid进程编号为1,其它进程都是它的后代。

然后,init线程载入系统的各个模块,比方窗体程序和网络程序。直至运行/bin/login程序,跳出登录界面,等待用户输入username和password。



计算机是怎样启动的?第6张

这个部分比較有意思。

由于在BIOS阶段,计算机的行为基本上被写死了。程序猿能够做的事情并不多;可是,一旦进入操作系统,程序猿差点儿能够定制全部方面。

所以。这个部分与程序猿的关系更密切。

第一步、载入内核

操作系统接管硬件以后。首先读入 /boot 文件夹下的内核文件。

计算机是怎样启动的?第7张

以我的电脑为例。/boot 文件夹以下大概是这样一些文件:


  $ ls /boot
  
  config-3.2.0-3-amd64
  config-3.2.0-4-amd64
  grub
  initrd.img-3.2.0-3-amd64
  initrd.img-3.2.0-4-amd64
  System.map-3.2.0-3-amd64
  System.map-3.2.0-4-amd64
  vmlinuz-3.2.0-3-amd64
  vmlinuz-3.2.0-4-amd64
  

第二步、启动初始化进程

内核文件载入以后。就開始执行第一个程序 /sbin/init。它的作用是初始化系统环境。

计算机是怎样启动的?第8张

因为init是第一个执行的程序,它的进程编号(pid)就是1。其它全部进程都从它衍生,都是它的子进程。

第三步、确定执行级别

很多程序须要开机启动。它们在Windows叫做"服务"(service),在Linux就叫做"守护进程"(daemon)。

init进程的一大任务,就是去执行这些开机启动的程序。

可是,不同的场合须要启动不同的程序,比方用作server时。须要启动Apache,用作桌面就不须要。Linux同意为不同的场合,分配不同的开机启动程序。这就叫做"执行级别"(runlevel)。也就是说,启动时依据"执行级别",确定要执行哪些程序。

计算机是怎样启动的?第9张

Linux预置七种执行级别(0-6)。

一般来说。0是关机,1是单用户模式(也就是维护模式),6是重新启动。

执行级别2-5,各个发行版不太一样,对于Debian来说,都是相同的多用户模式(也就是正常模式)。

init进程首先读取文件 /etc/inittab,它是执行级别的设置文件。假设你打开它,能够看到第一行是这种:


  id:2:initdefault:
  

initdefault的值是2,表明系统启动时的执行级别为2。

假设须要指定其它级别,能够手动改动这个值。

那么,执行级别2有些什么程序呢,系统怎么知道每一个级别应该载入哪些程序呢?......回答是每一个执行级别在/etc文件夹以下,都有一个相应的子文件夹。指定要载入的程序。


  /etc/rc0.d
  /etc/rc1.d
  /etc/rc2.d
  /etc/rc3.d
  /etc/rc4.d
  /etc/rc5.d
  /etc/rc6.d
  

上面文件夹名中的"rc",表示run command(执行程序)。最后的d表示directory(文件夹)。以下让我们看看 /etc/rc2.d 文件夹中究竟指定了哪些程序。


  $ ls  /etc/rc2.d
  
  README
  S01motd
  S13rpcbind
  S14nfs-common
  S16binfmt-support
  S16rsyslog
  S16sudo
  S17apache2
  S18acpid
  ...
  

能够看到,除了第一个文件README以外,其它文件名称都是"字母S+两位数字+程序名"的形式。字母S表示Start。也就是启动的意思(启动脚本的执行參数为start)。假设这个位置是字母K,就代表Kill(关闭),即假设从其它执行级别切换过来,须要关闭的程序(启动脚本的执行參数为stop)。后面的两位数字表示处理顺序。数字越小越早处理。所以第一个启动的程序是motd,然后是rpcbing、nfs......数字同样时,则依照程序名的字母顺序启动。所以rsyslog会先于sudo启动。

这个文件夹里的全部文件(除了README),就是启动时要载入的程序。

假设想添加或删除某些程序。不建议手动改动 /etc/rcN.d 文件夹,最好是用一些专门命令进行管理(參考这里这里)。

第四步、载入开机启动程序

前面提到,七种预设的"执行级别"各自有一个文件夹,存放须要开机启动的程序。不难想到,假设多个"执行级别"须要启动同一个程序,那么这个程序的启动脚本,就会在每个文件夹里都有一个拷贝。

这样会造成管理上的困扰:假设要改动启动脚本,岂不是每个文件夹都要改一遍?

Linux的解决的方法,就是七个 /etc/rcN.d 文件夹里列出的程序,都设为链接文件,指向另外一个文件夹 /etc/init.d ,真正的启动脚本都统一放在这个文件夹中。

init进程逐一载入开机启动程序,事实上就是执行这个文件夹里的启动脚本。

计算机是怎样启动的?第10张

以下就是链接文件真正的指向。


  $ ls -l /etc/rc2.d
  
  README
  S01motd -> ../init.d/motd
  S13rpcbind -> ../init.d/rpcbind
  S14nfs-common -> ../init.d/nfs-common
  S16binfmt-support -> ../init.d/binfmt-support
  S16rsyslog -> ../init.d/rsyslog
  S16sudo -> ../init.d/sudo
  S17apache2 -> ../init.d/apache2
  S18acpid -> ../init.d/acpid
  ...
  

这样做的还有一个优点,就是假设你要手动关闭或重新启动某个进程,直接到文件夹 /etc/init.d 中寻找启动脚本就可以。

比方,我要重新启动Apacheserver,就执行以下的命令:


  $ sudo /etc/init.d/apache2 restart
  

/etc/init.d 这个文件夹名最后一个字母d,是directory的意思。表示这是一个文件夹,用来与程序 /etc/init 区分。

第五步、用户登录

开机启动程序载入完成以后。就要让用户登录了。

计算机是怎样启动的?第11张

一般来说。用户的登录方式有三种:

  (1)命令行登录

  (2)ssh登录

  (3)图形界面登录

这三种情况,都有自己的方式对用户进行认证。

(1)命令行登录:init进程调用getty程序(意为get teletype),让用户输入username和password。

输入完毕后,再调用login程序。核对password(Debian还会再多执行一个身份核对程序/etc/pam.d/login)。

假设password正确,就从文件 /etc/passwd 读取该用户指定的shell。然后启动这个shell。

(2)ssh登录:这时系统调用sshd程序(Debian还会再执行/etc/pam.d/ssh ),代替getty和login,然后启动shell。

(3)图形界面登录:init进程调用显示管理器。Gnome图形界面相应的显示管理器为gdm(GNOME Display Manager),然后用户输入username和password。

假设password正确。就读取/etc/gdm3/Xsession,启动用户的会话。

第六步、进入 login shell

所谓shell,简单说就是命令行界面。让用户能够直接与操作系统对话。用户登录时打开的shell,就叫做login shell。

计算机是怎样启动的?第12张

Debian默认的shell是Bash,它会读入一系列的配置文件。上一步的三种情况,在这一步的处理,也存在差异。

(1)命令行登录:首先读入 /etc/profile,这是对全部用户都有效的配置。然后依次寻找以下三个文件。这是针对当前用户的配置。


  ~/.bash_profile
  ~/.bash_login
  ~/.profile
  

须要注意的是。这三个文件仅仅要有一个存在,就不再读入后面的文件了。比方。要是 ~/.bash_profile 存在,就不会再读入后面两个文件了。

(2)ssh登录:与第一种情况全然同样。

(3)图形界面登录:仅仅载入 /etc/profile 和 ~/.profile。

也就是说,~/.bash_profile 无论有没有,都不会执行。

第七步,打开 non-login shell

老实说,上一步完毕以后,Linux的启动过程就算结束了。用户已经能够看到命令行提示符或者图形界面了。可是。为了内容的完整,必须再介绍一下这一步。

用户进入操作系统以后,经常会再手动开启一个shell。这个shell就叫做 non-login shell,意思是它不同于登录时出现的那个shell,不读取/etc/profile和.profile等配置文件。

计算机是怎样启动的?第13张

non-login shell的重要性。不仅在于它是用户最常接触的那个shell,还在于它会读入用户自己的bash配置文件 ~/.bashrc。大多数时候。我们对于bash的定制,都是写在这个文件中面的。

你或许会问,要是不进入 non-login shell,岂不是.bashrc就不会执行了。因此bash 也就不能完毕定制了?其实,Debian已经考虑到这个问题了,请打开文件 ~/.profile,能够看到以下的代码:


  if [ -n "$BASH_VERSION" ]; then
    if [ -f "$HOME/.bashrc" ]; then
      . "$HOME/.bashrc"
    fi
  fi
  

上面代码先推断变量 $BASH_VERSION 是否有值,然后推断主文件夹下是否存在 .bashrc 文件,假设存在就执行该文件。

第三行开头的那个点,是source命令的简写形式,表示执行某个文件。写成"source ~/.bashrc"也是能够的。

因此。仅仅要执行~/.profile文件,~/.bashrc文件就会连带执行。

可是上一节的第一种情况提到过,假设存在~/.bash_profile文件。那么有可能不会执行~/.profile文件。解决问题非常easy,把以下代码写入.bash_profile即可了。


  if [ -f ~/.profile ]; then
    . ~/.profile
  fi
  

这样一来,无论是哪种情况。.bashrc都会运行,用户的设置能够放心地都写入这个文件了。

Bash的设置之所以如此繁琐,是因为历史原因造成的。早期的时候,计算机执行速度非常慢,加载配置文件须要非常长时间,Bash的作者仅仅好把配置文件分成了几个部分。阶段性加载。

系统的通用设置放在 /etc/profile,用户个人的、须要被全部子进程继承的设置放在.profile,不须要被继承的设置放在.bashrc。

顺便提一下,除了Linux以外, Mac OS X 使用的shell也是Bash。可是。它仅仅载入.bash_profile,然后在.bash_profile里面调用.bashrc。并且,无论是ssh登录,还是在图形界面里启动shell窗体,都是如此。


文章来源---阮一峰的网络日志

免责声明:文章转载自《计算机是怎样启动的?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MVC小系列(八)【改变Areas的FindView顺序】Python利用openpyxl带格式统计数据(2)- 处理mysql数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux使用Shell在线语音播报功能

在文件夹中创建一个sh文件,内容如下: #!/bin/bash say() { #mplayer -really-quiet "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=5&text=$*"; #mpg321 -q "http://tts.baidu....

Win7无法添加用户的问题

这段时间搞dcom的东西,然后按照网上说的,用dcomcnfg打开管理器,在dcom中我的电脑里面属性中把默认身份验证级别改为 无。然后再使用的时候,发现win7中的账户管理里面,什么账户都没有了,不能添加新的账户,也不能修改现有账户。郁闷死了。 后来搞了半天,发现是这个问题,把 无 改回 默认就可以了。 实际上改回默认后,dcom还是可以照样使用的。...

Windows10更新系统后,无法打开VMware

windows推送更新系统,更新完之后vmware就不能用了,打开如下图所示: 解决方案 1.win10打开—>此电脑—>属性—>打开控制面—>程序—>查看已安装的更新 点击‘“查看已安装的更新” 2,找到windows的最近更新补丁,右键,点击“卸载”。 3、卸载需要时间,卸载后“立即重启计算机” 4、重启后重新打开VM虚...

wlan接收器如何共享网络

无线局域网络(Wireless Local Area Networks; WLAN)是相当便利的数据传输系统,它利用射频(Radio Frequency; RF)的技术,取代旧式碍手碍脚的双绞铜线(Coaxial)所构成的局域网络,使得无线局域网络能利用简单的存取架构让用户透过它,达到“信息随身化、便利走天下”的理想境界。 工具/原料 方法/步骤 1、首...

Swt/Jface进度条 (转)

处理长时间的任务的时候常需要进度条显示,有几种实现方式1,普通的进度条 importjava.lang.reflect.InvocationTargetException;importorg.eclipse.core.runtime.IProgressMonitor;importorg.eclipse.jface.dialogs.ProgressMoni...

Linux中的LVM逻辑卷管理(转载)

这几天把自己的系统重做了一下,把自己电脑的硬盘分区做成了LVM(逻辑卷管理)类型的了。呵呵,以前老是会出现某一个分区的磁盘空间突然不足,然后就得放别的盘里。等东西放的多了用某一件东西时候就非常麻烦,都不知道自己的东西到底在哪个磁盘里面放着呢。。。这下好了,把硬盘做了LVM类型的磁盘就不用操这心了,现在先分少点,等以后不够用了,直接给不够用的磁盘往上加容量就...