Linux内核学习(2)文件系统的理解

参考书籍:《深入理解Linux内核》、《深度探索Linux操作系统 系统构建和原理解析》
参考博文:https://blog.csdn.net/titer1/article/details/44423031

(一)文件系统相关概念的辨析
1.文件系统是一个比较广泛的称呼,我们经常把三类不怎么相关但都属于文件系统技术的文件系统弄混淆。
(1)ext1-4 ,jffs1-2 ,yaffs1-2,ubifs,logfs
这一类文件系统描述的是数据在物理设备上存储的机制,比如磁盘中块组的结构。
(2)initrd,initramfs
这一类文件系统描述的是文件系统的装载方式,是装载磁盘上还是内存上。
(3)rootfs,tmpfs,proc
这一类是特殊文件系统的名字,所谓特殊文件系统就是内核将内核中的一种数据结构以文件的方式显示出来,它们是虚拟的没有物理设备与之对应的文件系统。
2.第二个比较容易混淆的是rootfs和根文件系统。
(1)很多人会说rootfs就是根文件系统,但这样说明显是不准确的,根据《深入理解Linux内核》一书中的如下描述,Linux安装根文件系统分为两个步骤,首先安装特殊文件系统rootfs,再在rootfs提供的空目录上安装实际根文件系统。
在这里插入图片描述
(2)这里有两个关键词,特殊和实际,我们常称呼的根文件系统是实际根文件系统,也就是我们在用户层看得到的根目录所在的文件系统,而且还包括执行应用层程序所需的其它进程、配置,库等等,也即包括/bin,/etc,/lib等等基本目录。而rootfs的根目录不一定会包含这些基本目录,这样我们就可以理清rootfs和根文件系统的关系:rootfs创建的目录作为根文件系统目录时它就是根文件系统,但是rootfs创建的目录还有可能不是根文件系统的目录,当实际根目录文件不是解压到rootfs目录(/),而是rootfs的子目录(/root/),这时我们不能将rootfs叫做根文件系统。之所以用户再看不到rootfs文件系统目录是因为在init阶段执行了chroot操作,也就是rootfs被隐藏了。
(3)还有一些术语也要区分,ramdisk,ramfs,initrd,initramfs。
① ramdisk是一种将内存看成磁盘设备的技术,当我们在linux内核源码里make menuconfig选择支持ramdisk后启动。在/dev下可以看到设备/dev/ram,这时将一块内存区域当做磁盘设备,我们可以通过mount命令将这个磁盘上的文件系统安装到指定目录中。
② initrd是init ramdisk的简称,就是在启动阶段使用此功能,将启动阶段需要的相关驱动和脚本打包到单个文件中,这样能够分离启动环境和运行环境。所以此功能需要支持ramfs(如下图目前的内核4.15.0中已经将这些功能合成了一项)。initrd主要在kernel2.6版本以前的版本使用,编译后会除了vmlinux外还有initrd.img,然后linux启动后会将镜像拷贝到内存中当做一块磁盘。然后将磁盘里面的内容拷贝到rootfs文件系统中执行相关其中的脚本。
③ ramfs是一种和ramdisk类似的技术,同样可以生成处于内存的文件系统。但是ramfs仅处于VFS,也就是没有实际文件系统格式(例如ext)的数据保存在内存上,所以ramfs进行umount后数据会自动删掉,再mount不会看到原数据,而ram disk umount后再mount数据还在。
④ initramfs也就是init ramfs的简称,功能和initrd一样,只不过实现方式是通过ramfs实现的。他们之间的主要区别是initramfs编译后和内核打包在一块,也就是只有一个zImage文件,当然如果我们在下面的编译菜单中的“initramfs source file”项不填写内容,那么内核也会生成默认的initramfs,但是这个时候我们常手动生成initrd.img,注意这里虽然叫做initrd.img,但其实还是initramfs。
Linux内核学习(2)文件系统的理解_第1张图片
3.还有一个术语需要说明一下,我们平常称“从Flash启动设备”、“从网络启动设备”等等,并不是处理器直接从那里读取第一条命令进行启动,而是在内核初始化完毕后执行init程序时从对应设备执行而已。
4.关于initramfs的作用,有的人描述为解决“鸡生蛋蛋生鸡”的问题,我一开始也是这样认为的,但是看了《深度探索Linux操作系统 系统构建和原理解析》的initramfs部分,我有了新的理解,书上的描述如下:
Linux内核学习(2)文件系统的理解_第2张图片
把这个问题全部当做“鸡生蛋蛋生鸡”的问题并不准确,因为产生这个问题有个前提,就是内核想要尽可能的简单,不愿包含过多的设备驱动。因为这个原因,设备驱动只能做成模块(.ko文件)执行动态加载,而要加载驱动又必须要把驱动文件放到文件系统中,所有才有“鸡生蛋蛋生鸡”问题。
另外还有一种方式针对init文件解释“鸡蛋”的问题:内核初始化完后会调用init程序挂载真正的根文件系统,而init本身就在根文件系统中,这样产生了“鸡蛋”悖论。但是仔细想想这个问题弄混淆了两个概念,当init程序在根文件系统中时是不需要挂载真正的根文件系统的,只有当init程序在initramfs中时才需要挂载真正的根文件系统。《深度探索Linux操作系统》书中就将init文件放在根文件系统中,然后将设备驱动编进kernel中,然后正常启动了内核和根文件系统。

(二)安装根文件系统
1.如果要详细弄清根文件系统启动方式,可以参考“https://blog.csdn.net/titer1/article/details/44423031 ”。 下面简要描述下使用initramfs的启动方式 :
(1)安装rootfs文件系统,创建根目录(/),创建特殊文件系统rootfs。
(2)初始化内核,拷贝initramfs中的文件到rootfs根目录,安装实际根文件系统。
(3)执行initramfs中的/init程序
(4)/init程序挂载真正的根文件系统

你可能感兴趣的:(linux开发)