huchuan2025/30-Resource/32-Work/对嵌入式Linux中的根文件系统的理解和解析.md

15 KiB
Raw Blame History

  • 本文时间为2015年

  • 虽然前面已经利用Busybox制作了根文件系统但是对于根文件系统的作用和普通的文件系统之间的区别还是有点模糊。通过查找资料总结了一下对根文件系统的理解也欢迎大家一起讨论。

  • 首先要明白的是“什么是文件系统”,==文件系统是对一个存储设备上的数据和元数据进行组织的机制==。这种机制有利于用户和操作系统的交互。在一篇oracle的技术文章中看到这样一句话“==尽管内核是 Linux 的核心,但文件却是用户与操作系统交互所采用的主要工具==。这对 Linux 来说尤其如此,这是因为在 UNIX 传统中,它使用文件 I/O 机制管理硬件设备和数据文件”这句话我是这样理解的在Linux没有文件系统的话用户和操作系统的交互也就断开了例如我们使用最多的交互 shell包括其它的一些用户程序都没有办法运行。在这里可以看到文件系统相对于Linux操作系统的重要性。下面是Linux文件系统组件的体系结构。 !Pasted image 20250315214515.png

  • 用户空间包含一些应用程序(例如,文件系统的使用者)和 GNU C 库glibc它们为文件系统调用打开、读取、写和关闭提供用户接口。系统调用接口的作用就像是交换器它将系统调用从用户空间发送到内核空间中的适当端点。VFS 是底层文件系统的主要接口。这个组件导出一组接口然后将它们抽象到各个文件系统各个文件系统的行为可能差异很大。有两个针对文件系统对象的缓存inode 和 dentry。它们缓存最近使用过的文件系统对象。

  • 每个文件系统实现(比如 ext2、JFS 等等)导出一组通用接口,供 VFS 使用。缓冲区缓存会缓存文件系统和相关块设备之间的请求。例如,对底层设备驱动程序的读写请求会通过缓冲区缓存来传递。这就允许在其中缓存请求,减少访问 物理设备的次数加快访问速度。以最近使用LRU列表的形式管理缓冲区缓存。==注意,可以使用 sync 命令将缓冲区缓存中的请求发送到存储媒体(迫使所有未写的数据发送到设备驱动程序,进而发送到存储设备)。==

  • 当我们在Windows下提到文件系统时你的第一反应是想到的是什么是不是Windows下的一些Fat32、NTFS等的文件系统的类型。而在 Linux中你可能会想到Ext2、Ext3但你还必须要有一个根文件系统的概念。根文件系统首先是一种文件系统该文件系统不仅具有普通文件系统的 存储数据文件的功能但是相对于普通的文件系统它的特殊之处在于它是内核启动时所mount的第一个文件系统内核代码的映像文件保存在根文件系统 中,==系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本如rcS,inittab和服务加载到内存中去运行==。我们要明白文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板上是没有办法真正的启动Linux操作系统的会出现无法加载文件系统的错误。

  • 那么根文件系统在系统启动中到底是什么时候挂载的呢?先将/dev/ram0挂载而后执行/linuxrc.等其执行完后。切换根目录,再挂载具体的根 文件系统.根文件系统执行完之后也就是到了Start_kernel()函数的最后执行init的进程也就第一个用户进程。对系统进行各种初始化的 操作。如果要能明白这里的过程的话可要好好的看看Linux内核源码了。下图展示了VFS内核文件系统的层次结构 !Pasted image 20250315215432.png

  • 根文件系统之所以在前面加一个”根“,说明它是加载其它文件系统的”根“,既然是根的话,那么如果没有这个根,其它的文件系统也就没有办法进行加载的。它 包含系统引导和使其他文件系统得以mount所必要的文件。根文件系统包括Linux启动时所必须的目录和关键性的文件例如Linux启动时都需要有 init目录下的相关文件在 Linux挂载分区时Linux一定会找/etc/fstab这个挂载文件等根文件系统中还包括了许多的应用程序bin目录等任何包括这些Linux 系统启动所必须的文件都可以成为根文件系统。

  • Linux启动时第一个必须挂载的是根文件系统若系统不能从指定设备上挂载根文件系统则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。因此一个系统中可以同时存在不同的文件系统。 在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂装mount。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂装时,要提供文件系统类型、文件系统和一个挂装点。根文件系统被挂载到根目录下“/” 上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt等再将其他分区挂接到/mnt目录上/mnt目录下就有这个分区的各个目录文件。  Linux根文件系统中一般有如下图的几个目录

    • /bin目录
      • 该目录下存放==所有用户都可以使用的、基本的命令==,这些命令在挂接其它文件系统之前就可以使用,所以/bin目录必须和根文件系统在同一个分区中。
      • /bin目录下常用的命令有cat,chgrp,chmod,cp,ls,sh,kill,mount,umount,mkdir,mknod,[,test等“[”命令其实就是test命令我们在利用Busybox制作根文件系统时在生成的bin目录下可以看到一些可执行的文件也就是可用的一些命令。
    • /sbin 目录
      • 该目录下存放系统命令,==即只有管理员能够使用的命令==当代桌面操作系统 没这个讲究了好像 回头看看服务器的),系统命令还可以存放在/usr/sbin,/usr/local/sbin目录下/sbin目录中存放的是基本的系统命令它们用于启动系统修复系统等与/bin目录相似在挂接其他文件系统之前就可以使用/sbin所以/sbin目录必须和根文件系统在同一个分区中。 /sbin目录下常用的命令有shutdown reboot fdisk fsck等本地用户自己安装的系统命令放在/usr/local/sbin目录下。
    • /dev目录
      • 该目录下存放的是设备文件设备文件是Linux中特有的文件类型在Linux系统下以文件的方式访问各种设备即通过读写某个设备文件操作某个具体硬件。比如通过"dev/ttySAC0"文件可以操作串口0通过"/dev/mtdblock1"可以访问MTD设备的第2个分区。
    • /etc目录
      • 该目录下存放着各种==配置文件==对于PC上的Linux系统/etc目录下的文件和目录非常多这些目录文件是可选的它们依赖于系统中所拥有的应用程序依赖于这些程序是否需要配置文件。在嵌入式系统中,这些内容可以大为精减
    • /lib目录
      • 该目录下存放共享库和可加载(驱动程序),共享库用于启动系统。运行根文件系统中的可执行程序,比如:/bin /sbin 目录下的程序。
    • /home目录
      • 用户目录,它是可选的,对于每个普通用户,在/home目录下都有一个以用户名命名的子目录里面存放用户相关的配置文件。用户文件。
    • /root目录
      • 根用户的目录,与此对应,普通用户的目录是/home下的某个子目录。
    • /usr目录 静态的只读数据
      • /usr目录的内容可以存在另一个分区中在系统启动后再挂接到根文件系统中的/usr目录下。里面存放的是共享、只读的程序和数据这表明/usr目录下的内容可以在多个主机间共享这些主要也符合FHS标准的。/usr中的文件应该是只读的其他主机相关的可变的文件应该保存在其他目录下比如/var。/usr目录在嵌入式中可以精减。
    • /var目录 /varVariable Data专用于存储 运行时动态生成的数据,其核心特点是 频繁变化 和 不可共享性
      • 与/usr目录相反/var目录中存放可变的数据比如spool目录mail,newslog文件临时文件。
    • /proc目录
      • 这是一个空目录常作为proc文件系统的挂接点proc文件系统是个虚拟的文件系统它没有实际的存储设备里面的目录文件都是由内核临时生成的用来表示系统的运行状态也可以操作其中的文件控制系统。
    • /mnt目录
      • 用于临时挂载某个文件系统的挂接点,通常是空目录,也可以在里面创建一引起空的子目录,比如/mnt/cdram /mnt/hda1 。用来临时挂载光盘硬盘、
    • /tmp目录
      • 用于存放临时文件,通常是空目录,一些需要生成临时文件的程序用到的/tmp目录下所以/tmp目录必须存在并可以访问。
    • /sys目录 *原文没写,比较复杂得单独写 * #未完成
  • 那我们利用Busybox制作根文件系统就是创建这上面的这些目录和这些目录下面的各种文件。 对于嵌入式Linux系统的根文件系统来说一般可能没有上面所列出的那么复杂比如嵌入式系统通常都不是针对多用户的所以/home这个目录在一般嵌入式Linux中可能就很少用到而/boot这个目录则取决于你所使用的BootLoader是否能够重新获得内核映象从你的根文件系统在内核启动之前。一般说来只有/bin/dev/etc/lib/proc/var/usr这些需要的而其他都是可选的。

  • 根文件系统一直以来都是所有类Unix操作系统的一个重要组成部分也可以认为是嵌入式Linux系统区别于其他一些传统嵌入式操作系统的重要特征它给 Linux带来了许多强大和灵活的功能同时也带来了一些复杂性。我们需要清楚的了解根文件系统的基本结构以及细心的选择所需要的系统库、内核模块和应用程序等并配置好各种初始化脚本文件以及选择合适的文件系统类型并把它放到实际的存储设备的合适位置下面是几中比较常用的文件系统。

    • JFFS2
      • JFFS嵌入式系统文件系统最早是由瑞典 Axis Communications公司基于Linux2.0的内核为嵌入式系统开发的文件系统。JFFS2是RedHat公司基于JFFS开发的闪存文件系统最初是针对RedHat公司的嵌入式产品eCos开发的嵌入式文件系统所以JFFS2也可以用在Linux, uCLinux中。
      • Jffs2: ==日志闪存==嵌入式系统文件系统版本2 (Journalling Flash FileSystem v2==)主要用于NOR型闪存==基于MTD驱动层特点是可读写的、支持数据压缩的、基于哈希表的日志型文件系统并提供了崩溃/掉电安全保护提供“写平衡”支持等。缺点主要是当文件系统已满或接近满时因为垃圾收集的关系而使jffs2的运行速度大大放慢。目前jffs3正在开发中。关于jffs系列文件系统的使用详细文档可参考MTD补丁包中mtd-jffs-HOWTO.txt。
      • ==jffsx不适合用于NAND闪存==主要是因为NAND闪存的容量一般较大这样导致jffs为维护日志节点所占用的内存空间迅速增大另外jffsx文件系统在挂载时需要扫描整个FLASH的内容以找出所有的日志节点建立文件结构对于大容量的NAND闪存会耗费大量时间。
    • yaffsYet Another Flash File System
      • yaffs/yaffs2是专为嵌入式系统使用 NAND型闪存而设计的一种日志型文件系统。与jffs2相比它减少了一些功能(例如不支持数据压缩)所以速度更快挂载时间很短对内存的占用较小。另外它还是跨平台的文件系统除了Linux和eCos还支持WinCE, pSOS和ThreadX等。
      • yaffs/yaffs2自带NAND芯片的驱动并且为嵌入式系统提供了直接访问文件系统的API用户可以不使用Linux中的MTD与VFS直接对文件系统操作。当然yaffs也可与MTD驱动程序配合使用。
      • yaffs与 yaffs2的主要区别在于前者仅支持小页(512 Bytes) NAND闪存后者则可支持大页(2KB) NAND闪存。同时yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。
    • CramfsCompressed ROM File System
      • Cramfs是Linux的创始人 Linus Torvalds参与开发的一种只读的压缩文件系统。它也基于MTD驱动程序。在cramfs文件系统中每一页(4KB)被单独压缩可以随机页访问其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间使系统可通过更低容量的FLASH存储相同的文件从而降低系统成本。
      • Cramfs文件系统以压缩方式存储在运行时解压缩所以不支持应用程序以XIP方式运行所有的应用程序要求被拷到RAM里去运行但这并不代表比 Ramfs需求的RAM空间要大一点因为Cramfs是采用分页压缩的方式存放档案在读取档案时不会一下子就耗用过多的内存空间只针对目前实际读取的部分分配内存尚没有读取的部分不分配内存空间当我们读取的档案不在内存时Cramfs文件系统自动计算压缩后的资料所存的位置再即时解压缩到 RAM中。另外它的速度快效率高其只读的特点有利于保护文件系统免受破坏提高了系统的可靠性。由于以上特性Cramfs在嵌入式系统中应用广泛。但是它的只读属性同时又是它的一大缺陷使得用户无法对其内容对进扩充。Cramfs映像通常是放在Flash中但是也能放在别的文件系统里使用 loopback 设备可以把它安装别的文件系统里。
    • 网络文件系统NFS (Network File System)
      • NFS是由Sun开发并 发展起来的一项在不同机器、不同操作系统之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段可以利用该技术在主机上建立基于NFS 的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。以上讨论的都是基于存储设备的文件系统(memory-based file system)它们都可用作Linux的根文件系统。实际上Linux还支持逻辑的或伪文件系统(logical or pseudo file system)例如procfs(proc文件系统)用于获取系统信息以及devfs(设备文件系统)和sysfs用于维护设备文件。
  • 补充 为什么设计/bin /usr/bin /usr/local/bin

    • /bin 最基本的,必须有的
    • /usr/bin 发行版中带的
    • /usr/local/bin 用户自己安装的
    • 优先级是先找最后的,然后中间最后前面