一、真实根文件系统是什么?
在上个文章中有描述rootfs的生成和挂载,这一部分应内核完成的,最终的结果就是当前进程的根目录就是rootfs文件系统的根目录。详见我之前记录
linux 从文件系统 到 rootfs理解
随后就需要将真实的文件系统加载,这个文件系统是什么呢?
它拥有有众多用户的用户程序,还有硬件设备的驱动程序,就像我们linux系统下,有很多系统工具app,也有比如显示器、磁盘等外设的驱动。与裸机的情况不同,无论是内核还是文件系统都是比较大的,一般是不会直接烧录到soc里面的,这些东西都是存储在外围设备,如磁盘中的。就比如linux操作系统也是我们装在硬盘里的吧。从下面我找的示意图可以看到,文件系统有有众多目录,文件,有些目录中还包含了大量的驱动。

linux文件系统结构
既然上面说的东西是存在外设上面,需要加载到内存中运行,那就必然需要通过外设的驱动来访问,而磁盘的设备驱动却又在文件系统内,那么问题来了,先有蛋,还是先有鸡呢?
二、如何加载文件系统的驱动?
- 直接将驱动集成到内核中
在嵌入式的环境下,有些开发板外设固定,启动用的emmc直接就在板子上,这时候很多厂家都是直接将外设驱动编译进内核中,内核被解压后会先加载文件系统所在设备的驱动,挂载真正的根文件系统,然后加载其他模块驱动。
- 创建过渡性质的文件系统
目标系统的硬件平台会有变动,就比如ubuntu可能运行在不同的硬件平台,根文件系统存在不同的介质上,比如sata硬盘,scsi硬盘等,或许以后还会有新的存储截至。出于兼容更多硬件平台的考虑,把所有驱动都编译进内核是不太明智的。
而且,有些文件系统是经过压缩、加密的,挂载前还需要解密,随着功能的丰富,如果这些都有内核处理,内核将会经常面临改动,而且灵活度差。所以需要一个临时的文件系统作为过渡。目前linux下支持有initramfs/initrd两种,现在普遍使用前一种,因为它是基于内存的,不需要再像initrd那样需要将文件系统当作一个块设备来管理。inird是一个基于ram的block device,是一个大小固定的内存块,可像disk一样格式化和挂载。initrd包括两种格式,一种是cpio-initrd,还有一个是image-initrd,当然这个不是我们今天的重点,而且image-initrd制作复杂,现在版本的内核基本都不采用这种方式加载驱动了。

访问两种initrd格式文件系统对比
所以就是这个initramfs会释放到内核开始创建的rootfs中,并initramfs中的init程序,该程序将探测硬件设备、加载驱动,挂载真正的文件系统,执行文件系统上的/sbin/init,进而切换到真正的用户空间。真正的文件系统挂载后,initramfs即完成了使命,其占用的内存也会被释放。
至此,文件系统彻底加载完成。