先安装文件系统,还是先安装操作系统?

先安装文件系统,还是先安装操作系统?

invalid s,我特别喜欢和聪明人交往,因为不用考虑他们的尊严——乔布斯

这个问题的答案取决于你是打算拿它当考试题学,还是真的想知道究竟发生了什么。

如果是考试题,那还是看标准答案吧。谁知道教授们会搞出什么逆天的新观点……总之你不照着来就肯定拿不了分——这也是这个问题反复出现在我的时间线上,但我却一直不想理睬的原因。不想误人子弟。

但如果你想知道这件事究竟是怎么回事,那不妨继续看下去。


文件系统究竟是什么?磁盘是什么

简单说,无论是 SSD 还是硬盘、光盘,都可以视为一个庞大的连续存储空间;这个存储空间的每个单元都有一个“地址”。

打个比方的话,各种存储器就好像装订起来的一个厚厚的笔记本,这个笔记本每页有 512 字节或者 4096 字节;视最大容量的不同,页码各有不同;视物理原理的不同,具体的编址 / 访问方式也不太一样。

但归根结底,任何存储器都可以看作一个庞大的连续存储空间。

文件系统是什么

我们可以简单粗暴的在笔记本上面随意的记录一些信息,比如:

dd if=/dev/random of=/dev/sdc

这个命令会把 sata 口上面的第三个磁盘的所有区域都用随机数写满 。

很显然,这样存储信息,将来是没法快速找到特定的信息的。

为了方便我们快速找到记录,可以在上面建立一个 map——还记得数据结构课程是怎么讲的吗?不记得了?这……

简单说,我们需要在磁盘空间最前面几页放一个“索引表”,表里每一行是一个包含{文件名,文件数据开始地址,文件大小,修改日期}等信息的一条记录。

现在,当我们需要找“2022 年 3 月 29 日的日记.txt”时,就可以先从这个索引表找到“文件名”等于“2022 年 3 月 29 日的日记.txt”的记录,然后顺着这条记录找到“文件数据开始地址”,再读取这个地址的内容,你要的信息就找到了。

这,其实就是一个最最简单、最最初级的“文件系统”了。

当然,这个“文件系统”是没法用的。它太简单、太原始了。

比如,开头的索引表,你设置了多少项,它至多就允许多少个文件;文件太多了,它就没有多余的项存放了;文件太少了,这个索引表就会有大量空白、浪费大量空间……

怎么办呢?

没错,可以搞“多级索引”,把“文件索引表”存到“目录文件”里。

不仅如此。实践中,我们还会面对很多很多其他必须解决的问题。比如性能方面的苛刻要求(可能需要配合寻道等物理机制综合考虑,比如 HDD 和 SSD 和光盘、磁带的文件系统格式往往就不能一样)、文件系统故障后的可恢复性、日志文件系统、权限、防碎片(HDD)防过度磨损(SSD)等等。

如此一条条需求排下来,文件系统就会变得极其的复杂;而且会有很多很多种不同方案——有些公司为了垄断,还会用专利保护自己的方案……

但,无论它千变万化,说白了文件系统的核心功能仍然是——通过索引,帮助用户在磁盘上迅速定位自己需要的信息。

磁盘分区

事实上,除非是软盘、光驱,否则我们一般并不能直接这么简单粗暴的怼一套文件系统进去。

在此之前,我们需要先“分区”;说白了就是在硬盘的第一个页面的指定位置填写分区起止扇区编号——对于 MBR 格式分区,这个分区表大小是极其有限的,至多只能填写四个分区(这就是主分区最大数量是 4 个这个技术限制的由来)。

当然你可以在扩展分区开头的分区表里面搞更多的“逻辑分区”,从而突破分区数量的限制——玩计算机不会嵌套简直没法活。

分区之后,我们就可以严格按照“分区表”的指示,在一块硬盘上分区存储多个文件系统了。

开机过程

不详细描述了。简单说就是上电后,CPU 里面的指令计数器是一个固定值,使得它在固定的位置(rom)读取指令、执行自检等操作,这个过程是 BIOS/ 固件控制的;自检完毕,它会根据 bios 的设置:

载入启动列表里第一个磁盘的第一个扇区(MBR 模式;gpt 模式不太一样但基本原理相似,关键点是多了个 bootloader/os 的签名认证过程),从而进入磁盘引导过程。

磁盘引导过程

MBR 的前 446 字节就是所谓的“主引导程序”;之后就是 64 字节的分区表(每个分区信息占用 16 个字节)和 MBR 结束标记 55AA。

这段主引导程序会被 bios 载入、然后交给 CPU 执行(跳转到引导程序开头);CPU 按照主引导程序的指示读取分区表、再从启动分区载入指定扇区的内容(另一个可以更大更复杂的引导程序),并执行它。于是执行权就完成了从 bios 到 mbr 再到引导程序的转移过程。

操作系统启动

引导程序往往是 os 厂商自己编写的;但也有开源的第三方引导程序,比如著名的 grub。

grub 的引导代码可以“安装”在 MBR、也可以写在 grub 专用分区的开头。

这段代码会读取 grub.cfg,根据它的配置展示菜单,允许用户选择启动哪个操作系统:

你选择后,它就载入对应操作系统的引导代码,把控制权交给它。

通过这种方式,我们可以在一台电脑上安装多个操作系统,并在启动时选择启动到哪一个。

当然,如果你不需要多系统支持,那么可以不管 grub;尤其是,Windows 安装时默认会直接覆盖 grub 的引导代码,使得其他操作系统无法启动——对策也很简单,重新安装一下 grub 就行了,数据并不会丢失;grub 也会自动识别 Windows,并不会导致 Windows 无法启动。

总之,明显可以看出,引导程序的启动是链式的,链条上的每一环都可以任意替换,并不影响后续引导过程。

引导程序会载入文件系统驱动——说白了就是一个函数库,可以识别操作系统所在分区文件系统格式、从而允许我们用统一的 open(路径 / 文件名)模式访问磁盘信息——然后载入 os kernel、再由 os kernel 完成剩下的启动过程。

操作系统安装安装映像引导

为了安装操作系统,我们往往需要一个“启动盘”,这个启动盘可以是光盘,也可以是 u 盘甚至硬盘、软盘……甚至是网卡。

引导过程其实和前面的操作系统引导是一样的。也是通过引导程序载入 os kernel;然后 os kernel 不会显示桌面(shell)、而是执行了安装程序[1]

操作系统安装

安装程序既然是程序,那自然是可以任意发挥的。

正常来说,安装程序会提示用户给硬盘分区、设置每个分区使用的文件系统格式、然后把操作系统内容复制到相应分区(的文件系统里面)、最后改写 MBR(写入主引导记录)以及分区指定位置(写入 grub 或者其他类似的、更复杂的后续引导程序;注意这一步一般是最后才做的,避免操作系统安装过程失败、却又改了引导程序,使得计算机无法启动)……

写完,重启,操作系统就启动了。

但,我们既然已经知道了本质,那完全可以“不正常”啊。

比如说,自光盘 /U 盘映像安装其实也是从光盘 /U 盘复制了操作系统文件、再把它们写入安装分区;那么,我们别下载整个操作系统了,仅仅搞一个很小的、可以运行的核心,然后从网络直接下载操作系统文件、写入安装分区行不行?

可以的。

比如 Linux 的 net install 映像就是这样搞的:这个映像本身极小,只有一个 kernel 和少量通用驱动;它会像正常操作系统一样完成引导过程、执行安装程序;然后安装程序会依序提示用户给硬盘分区、设置每个区的文件系统格式;之后,因为本地没有操作系统相关数据,它会自动从网上下载最新的操作系统文件并写入安装分区。

进一步的,大的 PC/ 笔记本生产商并不会使用操作系统自带的安装程序——提示太多、解压太慢了。

它们会自己开发一套“量产系统”,直接用类似 dd 之类的命令把操作系统文件(以及预装软件)以最高效率写入磁盘,不必人的干预。这种系统甚至可能是通过专用的、支持硬盘热插拔的机器、同时挂载若干个硬盘并同时给它们写入操作系统文件(也可能是类似 net install 模式,每台机器自动下载和自己相关的数据并自动安装)。

大批量装机时,这种系统是必需的。

其实我们自己也可以这样搞。

比如,你的操作系统装在 sda,这个硬盘出现 smart 警告了,要坏;于是你买了新硬盘;那么你完全可以这样在新的硬盘“安装”操作系统:

dd if=/dev/sda of=/dev/sdb   #假设新硬盘是 /dev/sdb

没错。无视“硬盘需要分区”以及“每个分区建立文件系统”这些步骤,把整个硬盘当成一个文件、直接逐字节复制到另一个硬盘、从它首部的 MBR 开始一口气覆盖到末尾,这样也是可行的——复制完了,关机,摘掉 sda,用 sdb 替代,重启电脑,“安装”已经完成。

更帅的是,这种“操作系统搬家术”施展成功之后,你不需要像平常安装操作系统一样重装任何软件、或者重新登陆任何 app。

它们都在。一切都在。就好像你仅仅是关了次机又开机了、甚至是机器进入休眠状态(休眠到磁盘STD Suspend to Disk)然后又恢复了——没问题,完全没问题!你在休眠前扔出的那颗手雷都还在空中翻滚![2]

你甚至可以玩的更疯狂一点。

比如,sda 是早年买的,只有 120G,还分了两个区,现在不够用了;你又买了个 1T 的新 SSD。那么,你可以先给新的 SSD 分区,比如 C 盘分 250G,D 分剩下的 700G 空间;然后,执行:

dd if=/dev/sda0 of=/dev/sdb0
resize2fs /dev/sdb0
dd if=/dev/sda1 of=/dev/sdb1
resize2fs /dev/sdb1

执行完毕,确认无误,关机,摘掉 120g 硬盘(或者改变启动顺序,用 1T SSD 启动),重启。

一切照旧,同样支持“休眠唤醒”,仅仅是分区空间变大了。

显然,我们完全可以对 Windows/MAC OS 使用的文件系统一无所知、然而却仍然可以完成“操作系统安装”过程,对吧(当然,如果你要同时完成扩容的话,还是得知道文件系统格式的)。

你看,操作系统安装也是一个“链条”;我们可以随意替代链条中的任意一环——不仅可以增加一些环节、减少一些环节、取代一些,还可以改变一些环节、融合一些环节、甚至可以通过技术手段改变某些看似无法改变的环节的先后顺序……

比如,可以把操作系统数据放在硬盘最靠前的位置,设置 C 盘最小容量,禁止用户把 C 盘容量设置的小于这个容量也禁止他改变 C 盘文件系统类型。等用户买到机器、第一次开机时再提示他分区——前面讲过,分区其实就是改变了 MBR 里面的分区表填写的数据,并不影响其他数据;唯一的问题就是文件系统建立时、写在里面的尺寸不对了。但这也不用担心,分区之后调整一下 C 盘文件系统尺寸即可(Linux 下可以用 resize2fs 命令完成这件事)。

没错,只要你看透了本质,哪怕“先装系统后给磁盘分区”都是完全可行的!

因此,这个问题无法回答。因为它并不是一个有效的问题。

并没有什么限制要求我们必须照什么规范来,压根不存在这个规范[3]。相反,我们可以想怎么玩就怎么玩。

只要你真的搞懂了相关问题,你就不应该问出这样的问题。