本篇文章主要介绍了" Linux和windows双系统启动问题之一(win7 + ubuntu1404 + legacy bios + mbr)",主要涉及到方面的内容,对于系统运维感兴趣的同学可以参考一下:
计算机启动磁盘分区表MSDOSMBR和GPTGUID partitiontable1 MBR分区表2 GUID partition tableGPT分区表多重系...
- 计算机启动
- 磁盘分区表MSDOSMBR和GPTGUID partitiontable
- 1 MBR分区表
- 2 GUID partition tableGPT分区表
- 多重系统启动
- BIOS和UEFI
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_record,https://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。

图1
为了能够突破最多4个分区的限制,对于每一个分区,又可以分为Primary和Extended。Extended又可以继续划分为Logical partition。实际上如果一个分区是Extended,那么它实际并不占用空间,当继续划分为Logical时,才会在每一个Logical partition的开头扇区写入EBR(Extended Boot Record)。可以参考https://en.wikipedia.org/wiki/Extended_boot_record, 下图2是含有逻辑分区的情况。

图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分区表