Knoppix|镜像格式二十年:系统镜像的螺旋进化( 二 )


开头我们提到了 , Knoppix 的想法就是“把装好的操作系统给压缩一下 , 放在光盘里 ,随用随解压” , 这样精心选择后的 2GB 的 Distro 就可以压到一张光盘里了 , 不过“随用随解压“不是说有就有的 , 文件系统访问块设备 , 是要找到块的偏移量的 , 压缩了之后 , 这个偏移量就并不那么好找了 , 全解压到内存里再找偏移并不那么容易 。
回到2000年 , 那时候还是2.2内核 , Knoppix 的作者 Klaus Knopper 在创立 Knoppix 之初就引入了一种压缩的(compressed) loop 设备 , 称为 cloop , 这种设备是一种特殊的格式 , 它包含了一个索引 , 从而让解压缩的过程对用户来说是透明的 , Knoppix 的 cloop 设备看起来就是一个大约 2GB 大的块设备 , 当应用读写一个偏移的数据的时候 , 它只需要根据索引解压缩对应的数据块 , 并返回数据给用户就可以了 , 无需全盘解压缩 。
尽管 Knoppix 把众多 distro 带上了 Live CD 的船 , 但是 , 众多后继者 , 诸如 arch、Debian、Fedora、Gentoo、Ubuntu 等等 distro 的 LiveCD , 以及大家熟悉的路由器上玩的 OpenWrt , 都并没有选择 cloop 文件 , 它们选择了和应用语义更接近的文件系统级的解决方案——Squashfs 。 Squashfs 压缩了文件、inode 和目录 , 并支持从 4K 到 1M 的压缩单元尺寸 。 同样 , 它也是根据索引按需解压的 , 和 cloop 的不同之处是 , 当用户访问一个文件的时候 , 它来根据索引解压相应的文件所在的块 , 而非再经过一层本地文件系统到压缩块的寻址 , 更加简单直接 。 事实上 , Knoppix 里也一直有呼声想要切换到 squashfs , 比如 , 2004年就有开发者在转换 knoppix 到squashfs 上 , 而且 , 一些测试数据似乎也表明 Squashfs 的性能似乎要更好一些 , 尤其在元数据操作方面 。
在 wiki 上是这么评价 cloop 的缺点的:

The design of the cloop driver requires that compressed blocks be read whole from disk. This makes cloop access inherently slower when there are many scattered reads, which can happen if the system is low on memory or when a large program with many shared libraries is starting.
A big issue is the seek time for CD-ROM drives (~80 ms), which exceeds that of hard disks (~10 ms) by a large factor. On the other hand, because files are packed together, reading a compressed block may thus bring in more than one file into the cache.
The effects of tail packing are known to improve seek times (cf. reiserfs, btrfs), especially for small files. Some performance tests related to cloop have been conducted.
我来画蛇添足地翻译一下:
cloop 的设计要求从磁盘上以压缩块为单位读取数据 。 这样 , 当有很多随机的读操作时 , cloop 就会显著地变慢 , 当系统内存不足或一个有很多共享库的大型程序启动的时候都很可能发生 。 cloop 面临的一个很大的问题是 CD-ROM 的寻道时间(约80毫秒) , 这在很大程度上超过了硬盘的查找时间(约10毫秒) 。 另一方面 , 由于文件可以被打包在一起 , 因此读取压缩块实际可能可以将多个文件带入缓存 。 这样 , 那些支持 tail packing 的文件系统(比如 reiserfs , btrfs)可能可以显著改善 seek 操作的时间 , 尤其是对于小文件更是如此 。 已经有一些与 cloop 相关的性能测试也证明了这些观点 。
当然 , 尽管有这些争论 , cloop 也仍然在 Knoppix 上存在 , 不过 , 这个争论最终随着2009年 squashfs 被并入 2.6.29 主线内核 , 应该算是分出胜负了 , 进入 kernel 带来的开箱即用换来的是压倒性的占有率和更好的支持 , Squashfs 的优势不仅在上述的 distro 用户之多 , 也在于支持了了各种的压缩算法 , 只用于不同的场景 。
Docker:Make Unionfs Great Again 斗转星移 , 不再年轻的 Live CD 也因为如此普及 , 而让人觉得并不新奇了 。 但是 , 技术圈也有轮回一般 , 当年被 Live CD 带红的 Union FS 们再一次被 Docker 捧红 , 焕发了第二春 。 一般地说 , 虽然 aufs 们支持多个只读层 , 但普通的 Live CD 只要一个只读镜像和一个可写层留给用户就可以了 。 然而 ,以 Solomon 为首的 dotCloud 的朋友们充分发挥了他们卓越的想象力 , 把整个文件系统变成了“软件包”的基本单位 , 从而做到了 #MUGA (Make Unionfs Great Again) 。
回想一下 , 从1993年的 Slackware 到今天的 RHEL , (服务端的)Distro 的所作所为 , 不外乎我开头提到的两件事情——安装和升级 。 从 rpm 到 APT/deb 再到 Snappy , 初始化好系统之后的工作的精髓就在于怎么更平滑地安装和升级、确保没有依赖问题 , 又不额外占据太多的空间 。 解决这个问题的基础就是 rpm/deb 这样的包以及包之间的依赖关系 , 然而 , 类似“A 依赖 B 和 C , 但 B 却和 C 冲突” 这样的事情仍然层出不穷 , 让人们不停地尝试解决了二十年 。


推荐阅读