最近在进行一些实验环境的配置,最终通过双系统实现了多系统的管理,而不仅限于虚拟机的方式。以此方式成功安装了Windows8.1 Pro和Windows 10,原文在此。
在此基础上进一步安装了 Ubuntu16.04 ,通过将Ubuntu系统的 iso 文件刻录至U盘中,并在启动时选择从U盘启动系统,则可进入系统的安装界面,选择对应的用于安装系统的分区即可进行安装。安装过程较为简单且资料充足,这里主要讨论的是关于如何在使用Windows自带的引导程序时增加对Ubuntu16.04的引导的问题。
被网上各种各样的碎片文章和内容淹没,所以在此记录了解到的信息,介绍启动引导的基本原理,并给出了一个不甚完美的解决方法(解决方法在最文章最后)。
查找的一些有用的资料:Windows8贴吧中一篇Windows引导过程简介,关于linux开机引导过程linux下的开机启动流程,修改BCD配置文件的bcdedit使用指导和其他,有关UEFI的问题的UEFI启动解析,Ubuntu论坛中的置顶问题。
一些小知识点的总结(资料来源:Dual boot with Windows):
(1)不同的Windows系统支持不同的固件启动模式和磁盘分区方式。且Windows基于固件启动模式强制规定了对应的磁盘分区方式,即UEFI模式只能对应GPT分区,而Legacy BIOS模式只能对应MBR分区(也称为msdos格式)。
(2)绝大多数的基于某种固件启动类型的linux启动加载器(boot loader)是无法引导或链式加载基于其他种类固件启动类型的启动加载器的。如若linux采用的是UEFI+MBR的启动方式,则其启动加载器无法加载基于BIOS+MBR或者UEFI+GPT启动模式的Windows系统。以上限制的特殊情况参见链接资源的Bootloader UEFI vs BIOS limitations部分;
引导方式的选择
在安装引导的过程中有两种选项:linux下通过GRUB引导和Windows下通过自带启动器引导。
前者操作简单,可以在linux的安装过程中进行设置,问题在于若linux只是当前系统下的一个辅助操作系统而不是主要使用系统,则开机过程会较为缓慢,而且若后续linux系统出现问题或被删除,会影响其他Windows系统的引导,存在潜在的问题(当然若是使用linux为主要系统,则使用其默认的引导是划算的)。
笔者最后成功的方式是建立两个系统引导程序,通过BIOS设置读取引导程序的顺序,若选择Linux引导则引导Linux系统,若选择Windows引导程序则进入Windows系统。
引导原理的介绍
Windows下的系统引导方式随着系统版本的变化有着差异,前面链接的资料有一定介绍。这里笔者的设置环境为 Win8.1 中文版。
现有的Windows引导方式主要有两种:Legacy + MBR 和 UEFI + GPT 方式。Legacy BIOS无法识别GPT分区表格式,所以也没有LegacyBIOS+GPT组合方式;UEFI BIOS可同时识别MBR分区和GPT分区,所以UEFI下,MBR和GPT磁盘都可用于启动操作系统。不过由于Windows限制,UEFI下使用Windows安装程序安装操作系统是只能将系统安装在GPT磁盘中(可以参考文章的第一部分)。现对其引导原理进行一定介绍。
名词解释:
MBR : Master Boot Record,主引导记录。主要构成为引导加载某一操作系统。
主引导扇区 : 包含MBR的扇区,一般也简称MBR,一般位于存储设备的第一个扇区。包含主引导记录(446bytes)、磁盘分区表(16bytes*4)和结束标志(0x55aa)。引自百度百科。
活动分区 : 是计算机系统分区,启动操作系统的文件都装在这个分区,Windows 系统下一般被默认为C盘。
电脑开机后,开始启动BIOS,开始BIOS自检,通过自检后,bios找到硬盘上的主引导记录MBR。
WinXP:
读取并运行主引导记录(Master Boot Record,MBR) --> 读入活动分区的引导扇区 --> NTLDR装入并初始化,将系统有实模式转化为平滑模式 --> 运行一个迷你文件系统驱动(支持FAT和NTFS格式) --> NTLDR读入boot.ini文件,根据其内容生成开机选项,对开机系统进行选择,并加载所选择系统的加载文件。来自百度百科和Blog。
Win7:
读取MBR中的硬盘分区表DPT --> 寻找活动分区,找到其中的引导记录PBR --> PBR搜索活动区中的启动管理器bootmgr(相当于xp里的ntldr) --> Bootmgr寻找活动分区中的boot文件夹中的BCD文件(启动配置数据,相当于xp里的boot.ini文件) ->根据BCD文件在显示器上显示多操作系统选择画面 --> 根据选择的系统寻找对应的盘里的windowssystem32winload.exe文件,并且将控制权交给winload.exe
以上两个系统均是传统的Legacy+MBR的引导方式,主要流程为 Legacy BIOS -->读取主引导扇区 --> 找到活动分区,并加载引导程序NTLDR/Bootmgr --> 根据配置文件boot.ini/BCD生成多系统引导的菜单 --> 根据选择的系统和配置文件中存储的路径加载对应的系统。(即所谓的链式装载,主引导记录是为了找到系统所在的分区,即活动分区)
对于UEFI的启动,UEFI+GPT的主要流程为 开机通电自检 --> 根据引导顺序扫描存储设备,读取FAT格式的EFI系统分区 -->执行启动文件(笔者为Bootx64.efi)--> 在此分区中加载启动管理器和读取配置的BCD文件 --> 进行操作系统的选择和对应文件的加载。
主要特点:
1.没有读取MBR
2.系统引导所需要的引导程序与配置文件放置在额外划分出来的FAT格式的磁盘分区上(而不像之前的引导方式一样引导程序和最终的系统文件均放置在活动分区中)。
3.设备通过上述分区中的bootmgfw.efi文件来读取BCD文件,用户选择系统后,BCD文件根据自身的配置内容加载系统引导文件winload.efi(对Windows而言)。
借助linux强大的文件系统操作功能,可以方便的查看系统EFI分区的结构。通过挂载EFI系统分区到指定文件夹,可以进行查看。
图示为笔者华硕笔记本Win8.1中文版的EFI分区(或称ESP分区,即EFI System Partition )文件结构图
分析:
1.Bootx64.efi是计算机默认的启动方式(Bios中指定)。即计算机总是通过Bootx64.efi来进行开机引导。这里的Bootx64.efi只是一个文件名,任何有效的efi文件均可以改为此名并用作引导;
2.Bootmgr.efi是Windows默认的启动方式。即Windows总是通过Bootmgr.efi来进行引导。当Bootx64.efi指向Bootmgr.efi时(或者说在这种情况下,Bootx64.efi文件实际是由Bootmgr.efi改名而来),就启动了Windows的引导流程,并通过BCD文件生成开机选项菜单;
解决方案
针对上述的引导流程记录,可以知道不论是传统的Legacy+MBR或者是UEFI+GPT格式,主要过程都是通过特定的启动管理器读取配置文件从而生成系统选择界面,并在选择系统后对特定系统文件进行加载,故而一般的解决方案为在配置文件中加入其他系统的引导信息,从而可以根据该信息找到其他系统。
网上的解决方法有:
1.使用Ubuntu下的Boot-repair进行启动修复,该操作可以借助安装有Linux安装程序的U盘来进行,具体可见Ubuntu帮助。但该方法是使用grub即Llinux系统对Windows系统进行引导。
2.使用Windows自带的引导程序对linux进行引导,即将Ubuntu的相关引导信息加入Windows引导程序的配置文件中(一般是修改boot.ini文件),从而通过Windows的引导程序进行引导。这种方法对于Windows XP和Windows 7更为有效,因为这两个系统的引导程序和配置文件都位于活动分区中,对其的修改更简单,而之后的Windows引导程序好像不再使用boot.ini作为配置文件了,引导的设置更加复杂了。具体引导设置可以参考这里。具体的操作流程包括将Linux的启动扇区作为一个文件拷贝至Windows的活动分区,并在boot.ini中设置一个指向该启动扇区文件的项目,从而使得引导程序可以根据该设置去引导Linux系统。
借助安装有linux安装程序的U盘,选择试用linux,找到安装linux启动模块的设备名,如/dev/sda8等,使用dd命令获得所需的文件。
dd if=/dev/sdax of=ubuntu.mbr bs=512 count=1 //从指定文件/dev/sdax读取数据,读取512个字节,并输出到ubuntu.mbr文件中,从而得到linux启动的mbr
再将该文件放置到默认开机Windows系统的活动分区,修改相关的boot.ini文件即可。
该种方法笔者做过尝试但并未成功。个人认为这应该是最符合自身需求的方式,但失败原因不详,望能得到指点。(好像有结论说该种方式只能在Legacy BIOS模式系统中使用)
3.通过Windows8.1自带的工具bcdedit来进行开机启动设置。该工具在Windows NT之后的系统中提供。可通过bcdedit工具修改Win8.1下的BCD配置文件 和 设置对应的引导文件路径,这样Windows引导程序可以根据配置文件内容生成对应的引导菜单,引导程序也可根据设置路径信息找到对应的系统程序。bcdedit的操作指令在文章开始的链接中有介绍。或者可以直接通过图形界面工具easyBCD进行配置。
若自行手动配置,则需要新建一个启动引导项,给出相应的引导文件所在分区和路径、引导描述等参数。该种方式对于Windows系统引导其他Windows系统,如Win8.1引导Win10启动是有效的。但貌似在Windows8.1中引导Linux系统无法成功(最大的问题在于无法设置对应的path路径)。图示为笔者设备双系统Win10的相关信息。
4.Ubuntu12.04以及后续版本引入了对EFI模式的支持,所以可以将Ubuntu的引导程序GRUB安装在设备的EFI分区中(原系统Win8.1在安装时会划分,可以在磁盘管理中定位),此操作会在EFI分区中生成引导Ubuntu的文件,从而可以引导Ubuntu,原帖。但该贴的内容仍旧是通过Linux系统来引导Windows系统。笔者这里并没有使用Linux系统来引导Windows系统,而是让两个系统的引导程序相互独立,想要使用另一个系统时,则通过BIOS修改引导程序的使用顺序。
首先将Ubuntu安装至EFI分区,其中的目录内容会发生改变,在EFI文件夹下新增了ubuntu的引导程序。
linux下的启动分区即EFI分区挂载在/boot/efi下(可以通过df指令查看)
可以看到原EFI目录中新增了ubuntu目录
目录中的内容如图所示,其中的grubx64.efi和shimx64.efi均可进行Ubuntu系统的引导。其中前者无法在开启安全启动选项下进行启动。
此方法的实际原理是Ubuntu和Windows使用两个不同的引导系统,通过BIOS可以设置使用引导程序的顺序。当默认首先使用bootx64.efi作为引导程序时,则会引导Windows系统,而首先使用grubx64.efi作为引导程序时,则会引导Linux系统。这样的两个系统之间无法进行相互引导,但也保证了两个系统本身的情况不会相互干扰。设备开机时总是会默认载入BIOS中设置的第一顺序的引导程序对应的操作系统。这种方法相当于将Linux启动引导安装在EFI分区,从而多出一个启动文件grubx64.efi。通过选择grubx64.efi/bootx64.efi来对不同的系统进行引导。
在之前的方法失败后,笔者退而求其次的选择了该方法并成功安装。