Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)

时间:2023-02-06 11:42:55

1.计算机启动

当我们在一个主机上安装多个系统时(如Win7和Ubuntu14.04),都会遇到开机启动哪一个系统的问题。这里典型的情况是先安装的是Ubuntu,然后再安装win7,就会出现ubuntu启动项不见的问题。我的电脑是legacy bios+mbr,多数解决方案是使用Windows的启动管理器EASYBCD,参考http://www.crazyant.net/781.html,新增entry,但是并不管用,可能会遇到找不到linux启动分区的情况。反正我的就不管用。另一种解决方案是在linux下使用grub2,可以参考http://blog.csdn.net/ethan_xue/article/details/7538568,但是在完成sudo update-grub后,直接重启,直接进入了一个grub的命令行。于是参考http://askubuntu.com/questions/121008/server-boots-to-grub-prompt-after-reboot,找打了解决方法。分以下几个步骤:
1. 在grub的命令行中敲ls,会列出很多分区,比如(hd0,msdos8),你需要明确你的linux安装在哪个分区比如我的是sda8。然后执行如下几个命令
2. set root=(hd0, msdos8)
3. linux /vmlinuz root=/dev/sda8 ro
4. initrd /initrd.img
5. boot
等待一会儿,就会启动ubuntu了。进入ubuntu后执行update-grub命令,再次重启,发现再次进入grub命令行界面。于是又重新执行上述步骤,进入ubuntu之后又执行grub-install –recheck/dev/sda,然后重启,结果成功了。经过多次重装系统之后,想搞清楚关于分区和多系统启动的原理,下面会详细讲述。

2.磁盘分区表MSDOS(MBR)和GPT(GUID partitiontable)

我们知道,不管是windows还是linux,都存放在磁盘中,并且由自己的启动程序boot loader启动。计算机开机的时候就得找到引导他们启动的boot loader的位置。而要找到boot loader,就必须要有描述boot loader位置的元数据信息。但是,计算机加电之后内存中并没有程序啊?怎么找到元数据信息呢?首先,我们需要知道的是,计算机在按下开关之后,就会运行第一个程序,但这个程序并不是操作系统的程序,这个程序实际上是固件(已经写入主板的程序),也就是BIOS(Basic Input/OutputSystem)。这个BIOS的作用就是做各种硬件检测,读取参数,并存入CMOS中。此时,BIOS的作用之一就是找到boot loader。不同的计算机厂商都是开发各自的BIOS,而boot loader在磁盘上,如果需要大家统一,最好的方法就是约定boot loader必须装在磁盘的某一个固定的位置(比如磁盘开始的第一个扇区的512Bytes)以便BIOS读取boot loader到内存。因此,早期的设计就是主开机记录MBR(Master Boot Record),里面装着boot loader,它有446Bytes。接着的64Bytes是分区表。MBR同时被Windows和Linux支持。关于MBR的设计,又是一个鸡生蛋蛋生鸡的问题。在计算机科学中,的确遇到很多这样的案例。比如我们现在使用的gcc和c语言程序的关系,记得大一那会儿一直搞不明白,感觉很奇怪。既然c语言程序要用gcc编译才能运行,而gcc本身又是c语言程序,那gcc是怎么被编译出来的,gcc吗?解答一是gcc由其他语言编译器编译出来。那其他语言的编译器又是什么编译器编译出来的呢?也就是说,总得有一个上帝一样的编译器,它一开始就不用编译。这个上帝一样的编译器到底是什么啊。学过汇编的人应该知道,汇编语言是最接近硬件的语言,如果你的程序是汇编语言写的,那么需要一个汇编器,但是最开始哪儿有汇编器。其实,汇编语言又叫助记符,每一个指令都对应着一个二进制编码。呵呵,上帝编译器其实就是人啊……计算机早期,其实都是自己在纸条上写完程序后,然后对照编码表,一步一步翻译成机器语言的。人脑是计算速度最慢的编译器,但却是计算机的上帝编译器。另一个案例是机器学习,有很多这样的问题,输入一批数据,训练,再用输出结果,调整参数再将输出作为输入。这样一来,就是先有输出还是输入的问题,但是问题是一开始输入和输出都没有。此时的办法就是人为设定一个输入,比如一批随机输入数据。最后,还有一个比较常见的就是对数据的描述信息,我们称之为元数据meta data。元数据就是一个链,一直指向目标数据,而同时目标数据中也可以含有发现元数据的能力,这样一个双向链中,也需要一个最初的元数据,而这个元数据可能就是人为设定死的。下面也来看看磁盘分区是怎么设计数据和元数据的。

2.1 MBR分区表

不管是Windows还是Linux都有分区,Windows上是C D E F 等,Linux上是/dev/sda1 /dev/sda2 /dev/sda3/dev/sda4等。磁盘开始512 Bytes分为:
- 主要开机记录区( Master Boot Record, MBR) :可以安装开机管理程序的地方,有446 Bytes
- 分区表( partition table) :记录整颗硬盘分区的状态,有64 Bytes
- 分区表中的每一项是16 Bytes,具体格式可以参考https://en.wikipedia.org/wiki/Master_boot_recordhttps://en.wikipedia.org/wiki/Extended_boot_record,每一个项目会记录分区的起始柱面号,占3 Bytes,这样一来,早期的MBR设计使得分区最大不能超过2.2T。最多只能划分64/16=4个分区,如下图1(图片来自鸟哥)的分区。Windows上可能叫CDEF盘,Linux上则是/dev/sda1 /dev/sda2 /dev/sda3/dev/sda4。
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
图1
为了能够突破最多4个分区的限制,对于每一个分区,又可以分为Primary和Extended。Extended又可以继续划分为Logical partition。实际上如果一个分区是Extended,那么它实际并不占用空间,当继续划分为Logical时,才会在每一个Logical partition的开头扇区写入EBR(Extended Boot Record)。可以参考https://en.wikipedia.org/wiki/Extended_boot_record, 下图2是含有逻辑分区的情况。
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
图2
上述的分区在Linux系统中的设备文件名分别如下:
- P1:/dev/sda1
- P2:/dev/sda2
- L1:/dev/sda5
- L2:/dev/sda6
- L3:/dev/sda7
- L4:/dev/sda8
- L5:/dev/sda9
你会发现没有sda3和sda4。因为1234都是保留的P,MBR格式逻辑分区必定都是从5号开始。
MBR 主要分区、延伸分区与逻辑分区的特性我们作个简单的定义:
- 主要分区与延伸分区最多可以有四笔( 硬盘的限制)
- 延伸分区最多只能有一个( 操作系统的限制)
- 逻辑分区是由延伸分区持续切割出来的分区;
- 能够被格式化后,作为数据存取的分区为主要分区与逻辑分区。延伸分区无法格式化;
- 逻辑分区的数量依操作系统而不同,在Linux系统中SATA硬盘已经可以突破63个以上的分区限制;

2.2 GUID partition table,GPT分区表

MBR是512 Bytes的一个扇区,分区有容量上的限制,如果你有一个80T的磁盘阵列,那么要使用所有的空间,就必须2TB这样分割下去,很麻烦。并且MBR只有一个,如果坏掉就无法修复了。GPT是新的分区表,它有34个叫LBA(Logical Block Address),默认512 Bytes,从LBA0开始,这样LBA0就和MBR是相容的。
与 MBR 仅使用第一个512Bytes区块来纪录不同, GPT 使用了 34 个 LBA 区块来纪录分区信息!同时与过去 MBR 仅有一的区块,被干掉就死光光的情况不同, GPT 除了前面 34 个LBA 之外,整个磁盘的最后 33 个 LBA 也拿来作为另一个备份!这样或许会比较安全!
详细的结构有点像下图3的模样:
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
图3
虽然新版的 Linux 大多认识了 GPT 分区表,不过,在磁盘管理工具上面, fdisk 这个老牌的软件并不认识 GPT 喔!要使用 GPT 的话,得要操作类似 gdisk 或者是 parted 指令才行! 另外,开机管理程序方面, grub 第一版并不认识 GPT !得要 grub2 以后才会认识的!并不是所有的操作系统都可以读取到 GPT 的磁盘分区格式!同时,也不是所有的硬件都可以支持 GPT 格式喔!是否能够读写 GPT 格式又与开机的检测程序有关!

3.多重系统启动

认识到分区和开机管理程序之后,我们就来看看多重系统启动的原理。每一个操作系统都有开机管理程序boot loader。Boot loader一般都在MBR或者EBR的446Bytes中。当BIOS首先读取到MBR中的boot loader时,这个boot loader就会进行操作系统的启动工作。Boot loader的主要任务是:
提供菜单:使用者可以选择不同的开机项目,这也是多重开机的重要功能!
载入核心文件:直接指向可开机的程序区段来开始操作系统;
转交其他loader:将开机管理功能转交给其他loader负责;
第3个特点就是完成多重系统启动的关键。实际上,并不只是磁盘的第一个扇区MBR中有boot loader,磁盘的其他分区的开头扇区都可以安装boot loader,这也是多个操作系统可以存放在不同分区并启动的原因。如果一个操作系统的bootloader能够有转交功能,那么就可以实现多重系统启动了。多个系统启动就是通过转交功能链进行的。
我们举一个例子来说,假设你的个人计算机只有一个硬盘,里面切成四个分区,其中第一、二分区分别安装了Windows及Linux, 你要如何在开机的时候选择用Windows还是Linux开机呢?假设MBR内安装的是可同时认识Windows/Linux操作系统的开机管理程序, 那么整个流程可以图4如下:
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
图4
MBR中的boot loader首先会给出菜单,选择直接启动Windows或者进入Linux的Boot loader,如果选择linux boot loader,那么就会继续进行菜单选择,发现只有Linux,直接启动Linux。这里的关键在于BIOS读取的MBR中的boot loader是否有提供菜单和转接功能。
一个典型的例子是,先安装Linux,再安装Windows,此时就找不到Linux了。因为Windows的boot loader会覆盖掉MBR,而windows的boot loader只认自己,所以就无法再打开Linux了。此时,就需要修改MBR的boot loader,使其能够同时找到Windows和Linux,可用的工具包括Windows的EASYBCD个Linux下的grub。Grub2就支持多重开机,因此Linux下会用grub来写入MBR来完成多重开机功能。

4.BIOS和UEFI

关于BIOS和UEFI(Unified Extensible FirmwareInterface),他就是BIOS的升级版本而已。BIOS不能读取GPT,但是UEFI可以读取。而且UEFI加入了一个所谓的安全启动 ( secureboot) 机制,这个机制代表着即将开机的操作系统必须要被 UEFI 所验证,否则就无法顺利开机!微软用了很多这样的机制来管理硬件。不过加入这个机制后,许多的操作系统,包括 Linux ,就很有可能无法顺利开机!所以,某些时刻,你可能得要将UEFI 的 secureboot 功能关闭, 才能够顺利的进入Linux。传统环境一般是legacy bios+mbr,比如我以前的hp compaq320就是这种情况,里面安装的是win7+ubuntu14.04双系统,使用的是grub2开机引导程序,这是win7及以下的winxp都支持的组合,现在新电脑一般都是UEFI+GPT(联想小新700就是),XP是不支持的,并且win7 64bit才支持UEFI+GPT。查看自己电脑是legacy bios还是UEFI,可以按下组合键win+R在运行中输入msinfo32,可以看到是BIOS还是UEFI,在右击我的电脑->管理->磁盘管理,磁盘上右击属性,进入卷,可以查看是MBR还是GPT分区表格式。
对于UEFI相对于BIOS的优点,可以参考http://www.iruanmi.com/what-is-gpt-and-what-is-uefi/,里面也给出了支持UEFI+GPT启动的windows系统版本,下表列出了Windows各版本操作系统对GPT磁盘的支持程度:
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
32位Windows对GPT分区支持情况
Linux和windows双系统启动问题之一(win7 + ubuntu14.04 + legacy bios + mbr)
64位Windows对GPT分区支持情况

安装系统前一定搞清楚你的电脑主板是否支持UEFI,然后分区表是MBR还是GPT。关于主板是否支持UEFI,如果还没有安装任何系统的机器,就得进入BIOS先看看,要通过UEFI方式启动Windows7/8,电脑需要支持UEFI启动。预装Win8的电脑都支持UEFI启动。近两年的主板很多也都支持UEFI启动。开机出现品牌标识按F2(或者DEL、ESC等按键,不通品牌按键不通)进入BIOS/UEFI设置,在Boot项或类似项中查看有无EFI/UEFI相关选项,如果有,那么说明电脑支持UEFI启动。

参考:《鸟哥的私房菜》基础篇 第四版 第二章
BIOS和UEFI:
http://www.ihacksoft.com/uefi.html
http://www.voidcn.com/blog/hanwang3/article/p-4839839.html
多系统启动:
http://blog.csdn.net/canghai1129/article/details/38655899
http://blog.csdn.net/ethan_xue/article/details/7538568
http://askubuntu.com/questions/121008/server-boots-to-grub-prompt-after-reboot
http://wiki.jikexueyuan.com/project/learn-linux-step-by-step/boot-loader.html
http://www.everydaylinuxuser.com/2015/11/how-to-install-ubuntu-linux-alongside_8.html