---- 整理自 王利涛老师 课程
实验环境:宅学部落 www.zhaixue.cc
文章目录
- 15. 根文件系统
- 15.1 根文件系统的基本概念
- 15.2 挂载根文件系统的三种方式
- 15.3 根文件系统的挂载
- 15.3.1 rootfs 文件系统的概念
- 15.3.2 root= 参数分析
- 15.3.3 根目录“ / ”
- 16. 使用 initrd 作为根文件系统:CPIO 格式
- 16.1 initrd 和 ramdisk
- 16.2 内核配置
- 16.3 uboot 配置
- 16.4 制作 initrd 镜像
- 16.5 initrd 挂载过程分析
- 16.5.1 CPIO initrd 挂载过程分析
- 16.5.2 rdinit=/linuxrc 的启动
- 17. 使用 initrd 作为文件系统:ramdisk 格式
- 18. 使用 initramfs 作为根文件系统
- 18.1 initramfs 配置挂载过程
- 18.2 initramfs 挂载过程分析
- 19. 基于内存的文件系统:tmpfs
- 20. 文件系统的自动挂载
- 21. 文件系统的性能指标
上一篇不迷路: 06-07 - 文件系统(下)
15. 根文件系统
15.1 根文件系统的基本概念
- 什么是根文件系统?
- 根文件系统和一般文件系统有什么区别?
- 为什么需要根文件系统?
- 根文件系统的目录
- VFS 和根文件系统是什么关系?
- 如何指定根文件系统?
15.2 挂载根文件系统的三种方式
15.3 根文件系统的挂载
15.3.1 rootfs 文件系统的概念
- rootfs 的作用
- 子文件系统挂载到父文件系统上,那么最上层文件系统挂载到哪里?根文件系统肯定是挂载到根目录上,根目录是哪里来的?这就是 rootfs 的作用,在挂载根文件系统之前,完成一些基本环境的初始化,后续才能去挂载我们真正的根文件系统。
- 为什么不直接挂载分区,而先使用 rootfs?
- rootfs 和根文件系统是什么关系?
- 不是一个概念
- rootfs 和根目录的关系?
- 第一个根目录 “ / ” 何时创建的?
rootfs 文件系统设置了自己的根目录和当前目录为 " / "。
15.3.2 root= 参数分析
- root=/dev/mmcblk0 挂载 SD 卡为根文件系统
- root=/dev/nfs 挂载NFS为根文件系统:根据 root 参数挂载指定的根文件系统
- noinitrd 启动参数
- init=/linuxrc 启动
回到这里的代码:
我们当前进程的当前目录 current->pwd
设置为了 "/root"
目录。但是当前进程的根目录 current->root
还是 "/"
。
再回到代码的这里:
init_mount 改变挂载点,NFS 文件系统本来挂载在"/root" 目录,现在移动到根目录 “/”,如图中的红色虚线。
init_chroot 将当前目录也就是 “/root” 设置为根目录 “/”,如图中的红色实线。这样,NFS 就成了根文件系统。
15.3.3 根目录“ / ”
- 作用是什么?
- 什么时候初始化的?
- 根文件系统和根目录是什么关系?
- rootfs 的根目录: /
- NFS 的根目录 :
/root -> vfsmount->mnt_root
- 一个系统中允许多个 ”/” 吗?
- 根目录可以切换吗?
16. 使用 initrd 作为根文件系统:CPIO 格式
initrd 总的来说目前有两种格式:image 格式和 cpio 格式。image 格式也叫文件系统镜像文件(老式块设备的 initrd 文件),主要在 linux 2.4 内核中使用流行;在linux 2.5 内核开始引入 initramfs 技术,initramfs 实际上已经克服了 imgae-initrd 的缺点,本质上也是 cpio 格式的 initrd,只不过是和内核编译到了一个 image 文件,放在了 .init.ramfs 段内;到 linux 2.6 的内核支持两种格式的 initrd,即 image-initrd 和 cpio-initrd,此时的 cpio-initrd 文件已不再编译进内核而单独成一文件,使用 cpio 工具生成。https://blog.51cto.com/u_15064644/4817854
16.1 initrd 和 ramdisk
- 什么是 ramdisk?
- 什么是 initrd?
- 为什么会有 initrd?
- Linux 内核在初始化之后会启动一个 init 进程,在这个 init 进程中挂载根文件系统,但是 init 进程的二进制 bin 文件是存储在文件系统中的,所以这就有了先有鸡还是先有蛋的问题。为了解决这个问题,内核采用了两步走的方法:除了内核镜像外,还有一个独立的 initrd.img 镜像,内核会先 mount 这个镜像作为根文件系统,然后执行 initrd 中的 /linuxrc 或者 /init 来挂载真正的根文件系统。
- initrd 和 ramdisk 的关系,其实就像系统备份镜像和 C 盘的关系,普通的根文件系统数据(包括二进制文件、脚本、配置文件、目录等)是存放在磁盘中的,因为 ramdisk 是在内存中模拟的一块磁盘设备,断电后数据不会永久保存,所以我们需要一个备份镜像保存在磁盘上,在系统启动时,将备份数据镜像加载到内存中的 ramdisk 中就可以了,而 initrd 就是根文件系统的备份镜像,为了节省体积,还会支持各种压缩格式,加载到内核中再解压。
- 如何制作 initrd 镜像?
通过 ramdisk
通过 loopback
cpio 格式:find . | cpio -o -H newc | gzip -c > ../initrd.gz
- 如何设置 root、initrd 参数挂载 initrd?
root=
initrd=
rdinit=/linuxrc
16.2 内核配置
因为 initrd 基于 ramdisk 实现,所以内核需要支持 initrd 和 ramdisk 功能。
注:ramdisk 大小设置为了 4M,下面会用到。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig -j$(nproc)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig -j$(nproc)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j$(nproc)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage LOADADDR=0x60003000 -j$(nproc)
16.3 uboot 配置
使用 initrd 作为根文件系统,需要在启动参数中指定,然后传输给内核,在嵌入式系统中,一般可以通过 uboot 的 bootcmd 和 bootargs 来传递。
tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;tftp 0x62000000 initrd.gz;setenv bootargs 'initrd=0x62000000,4M root=/dev/ram0 rw rdinit=/linuxrc console=ttyAMA0';bootm 0x60003000 - 0x60500000;
16.4 制作 initrd 镜像
- 基于之前的 NFS 镜像文件制作 initrd 镜像,NFS 镜像文件如下,大小为 26M,大于 4M。
- 先拷贝一份 NFS 的镜像文件,然后删除其中 lib 目录下的库文件,只保留 libc 库。
find . | cpio -o -H newc | gzip -c > ../initrd.gz
- 加载 initrd 结果。
16.5 initrd 挂载过程分析
find . | cpio -o -H newc | gzip -c > ../initrd.gz
16.5.1 CPIO initrd 挂载过程分析
do_initcalls 就会执行到如下函数:
16.5.2 rdinit=/linuxrc 的启动
回到前面:
17. 使用 initrd 作为文件系统:ramdisk 格式
- 制作一个 ramdisk 镜像
- ramdisk 格式的 initrd 挂载过程分析
- 使用 initrd 的优点、缺点: page cache \ 地址空间
需要修改 boot 配置中的 bootcmd 参数:
# 将之前的 initrd.gz 改成 initrd
CONFIG_BOOTCOMMAND="tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;tftp 0x62000000 initrd;setenv bootargs 'initrd=0x62000000,4M root=/dev/ram0 rw rdinit=/linuxrc console=ttyAMA0';bootm 0x60003000 - 0x60500000;"
前面过程一样,一直走到这里:
18. 使用 initramfs 作为根文件系统
- 相比 initrd(一种 cpio 制作的,一种传统 ramdisk 方式制作的),initramfs 的优势有哪些?
- 启动参数
- root:initramfs 作为根文件系统,root、init 不用设置,只需要指定文件系统的源目录就可以了
- 文件系统中默认要有一个 init 文件
18.1 initramfs 配置挂载过程
- 使用 initramfs 的内核配置
使用之前创建的 ramdisk 路径,同时将路径下的 linux 更名为 init 。然后再开始编译内核。
- 使用 initramfs 的 u-boot 编译配置
tftp 0x60003000 uImage;tftp 0x60800000 vexpress-v2p-ca9.dtb;setenv bootargs 'console=ttyAMA0';bootm 0x60003000 - 0x60800000;
18.2 initramfs 挂载过程分析
- initramfs 的挂载过程分析
- Linkscript: arch/arm/kernel/vmlinux.lds
- Head file: include/asm-generic/vmlinux.lds.h
- Makefile: usr/Makefile
前面过程和之前章节一样:
这里着重分析一下两个参数:__initramfs_start
和 __initramfs_size
19. 基于内存的文件系统:tmpfs
- 内存的文件系统
- ramfs VS ramdisk
- ramfs VS tmpfs
- tmpfs 的优点:
- 快、不用格式化、动态调整大小、扩展性好
- tmpfs 的实现:
linux-5.10.4/mm/shmem.c
- tmpfs 的应用领域
- 临时目录、临时文件
- tmpfs 的挂载:
mount -t tmpfs -o size=4m tmpfs /tmp
20. 文件系统的自动挂载
- 文件系统挂载方式
- 内核挂载、启动参数、自动挂载
- 根文件系统的常用目录
- 启动脚本
- 文件系统的自动挂载
注意:实验前将文件系统还原成 NFS 配置,包括 boot 和 kernel。
21. 文件系统的性能指标
- 不同应用场景
分布式
服务器、PC
消费电子 - 文件系统得到性能指标
文件名长度、最大文件数、最大分区、最大文件大小
挂载速度、读写速度、稳定性、日志 - 如何选型文件系统?
- 常见的文件系统
- Windows:FAT16、FAT32、NTFS
- Linux:ext2、ext3、ext4、btrfs、zfs
- 光盘:ISO9660
- 网络文件系统:SMBAFS、CIFS、NFS