`

基于 SquashFS 构建 Linux 可读写文件系统

 
阅读更多

基于 SquashFS 构建 Linux 可读写文件系统

在当前的嵌入式操作系统开发中,Linux 操作系统通常被压缩成 Image 后存放在 Flash 设备中。在系统启动过程中,这些 Image 被直接挂载到根文件系统, 然而这时的根文件系统是只读的, 用户不能在这个文件系统中进行任何写的操作。 如果把 Image 解压后直接拷贝到内存中,也可以实现写的功能,但是嵌入式系统一直存在内存大小方面的限制,所以将整个 Linux 系统拷入内存是不可取的。 本文将介绍一种直接挂载 Image 到根目录下,同时实现文件系统可读写的功能。

秦 志雷, 软件工程师, IBM

2013 年 7 月 01 日

  • +内容

嵌入式 Linux 启动过程

本文所描述的的 Linux Image 由 BootLoader、kernel、initrd、rootfs 组成,它们共同存在于一个可以启动的存储设备中(本文以 USB 为例)。组成架构如下:

图 1. 可启动 linux 镜像文件结构
aaa

各个模块的作用如下:

  • Boot Loader:由 BIOS 加载,用于将后续的 Kernel 和 initrd 的装载到内存中
  • kernel:为 initrd 运行提供基础的运行环境
  • initrd:检测并加载各种驱动程序
  • rootfs:根文件系统,用户的各种操作都是基于这个被最后加载的文件系统

其调用顺序是 Boot Loader->kernel->initrd->rootfs。

当机器上电时首先 BIOS 会启动,然后装载 USB 设备中的 Boot Loader、kernel,、nitrd 到内存中,由于这些文件大小总和小于 10M,所以我们直接拷贝到内存中再执行不会有问题。

最后要加载的 rootfs 是用户最终进行读写操作的文件系统。

  • 在非嵌入式系统中,这部分文件通常储存在可直接读写的硬盘上,因此直接挂载到根目录后(例如:mount /dev/sda1 /mnt)就可以进行读写操作。
  • 在嵌入式系统中,它是一个压缩的文件系统,大小通常是好几百兆,解压后的大小都超过 1G,如果直接 mount 到系统目录,那么系统目录是只读的,不可进行写入操作。而如果把它加压到内存中可以实现读写的操作,但是这么大的文件直接解压到内存中对于嵌入式设备来说是不可接受的。因此我们需要找到一种不拷贝 rootfs 到内存中,同时又可以对最终的根文件系统进行读写的方法。

只读式压缩文件系统介绍

在嵌入式的环境之下,内存和外存资源都需要节约使用。如果使用 RAMDISK(把内存当作 disk)方式来使用文件系统,那么在系统运行之后,首先要把外存 (Flash) 上的映像文件解压缩到内存中,构造起 RAMDISK 环境,才可以开始运行程序。但是它也有很致命的弱点。在正常情况下,同样的代码不仅在外存中占据了空间 ( 以压缩后的形式存在 ),而且还在内存中占用了更大的空间 ( 以解压缩之后的形式存在 ),这违背了嵌入式环境下尽量节省资源的要求。以下两种方案的诞生就是为了解决这个问题:

CramFS

CramFS 文件系统是专门针对闪存设计的只读压缩的文件系统,它并不需要一次性地将文件系统中的所有内容都解压缩到内存之中,而只是在系统需要访问某个位置的数据的时侯,马上计算出该数据在 CramFS 中的位置,将其实时地解压缩到内存之中,然后通过对内存的访问来获取文件系统中需要读取的数据。CramFS 中的解压缩以及解压缩之后的内存中数据存放位置都是由 CramFS 文件系统本身进行维护的,用户并不需要了解具体的实现过程,因此这种方式增强了透明度,对开发人员来说,既方便,又节省了存储空间。

SquashFS

SquashFS 也是一个只读的文件系统,它可以将整个文件系统压缩在一起,存放在某个设备,某个分区或者普通的文件中。如果您将其压缩到一个设备中,那么您可以将其直接 mount 起来使用,而如果它仅仅是个文件的话,您可以将其当为一个 loopback 设备使用。

更多信息请参考“SquashFS”和“CramFS”。

本文主要介绍基于 SquashFS 的可读写文件系统构建。

 

Squash 压缩文件系统的创建

"下载并安装 Squash 工具"

步骤 1:创建空的根文件系统,文件系统的大小为 65536 × 24000/1024/1024=1.5G。接下来我们会在这个空的根文件系统中存放文件。

注释:

dd: 读取源文件的内容并创建一个新文件,if 指定源文件内容,of 指定新文件名字,bs 和 count 指定新文件的大小 
mke2fs: 将新创建的 rootfs 格式化为 Linux 可识别的文件系统

清单 1. 创建空的根文件系统
 dd if=/dev/zero of=rootfs bs=65536 count=24000 
 mke2fs -F rootfs


步骤 2:挂载空的根文件系统,将 1.5G 的文件系统挂载在 mnt 目录下,然后通过 mnt 目录将内容写入根文件系统。

清单 2. 挂载空的根文件系统
 mkdir mnt 
 mount rootfs mnt -o loop

步骤 3:拷贝根文件目录的内容到文件系统

清单 3. 拷贝根文件目录统
 cp -rp yourRootDir mnt 
 umount mnt

拷贝完后根文件系统的内容,如图 2 所示:

图 2. 根文件系统内容
aaa


步骤 4:完成根文件系统的创建,这时的 rootfs 没有被压缩,接下来我们用工具将其压缩成 Squash 格式的文件系统

注释:

mksquashfs-4.1 是在安装 Squash 工具的过程中生成的命令,用于将一个文件夹下的内容打包并压缩成一个文件系统。其后第一个参数为文件夹,第二个参数为生成的文件系统。

清单 4. 创建根文件系统
 mkdir squashfs-dir 
 mv rootfs squshfs-dir 
 mksquashfs-4.1 squashfs-dir squashRootfs

到这里我们就完成了 Squash 压缩文件系统的创建。接下来我们将讨论如何在 Linux 启动的过程中加载这个压缩文件系统。

 

加载压缩文件系统所使用的工具

在加载压缩文件系统之前,我们需要确定您的 Linux 内核支持这种文件系统。 Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略。

确保在 initrd 中已经集成“device-mapper

 

加载 Squash 压缩文件系统

可读写文件系统原理如图 3 所示:

图 3. 可读写文件系统原理
aaa

squashRootfs 里面存储了我们原始的根文件系统,我们在根文件系统中所有的写操作会直接写入 cowfile.out(cow:copy-on-write), 当我们读取根文件系统时,如果读取的内容没有变化,将直接从 squashRootfs 中读取,如果读取的内容被更新过,将从 cowfile.out 中读取。cowfile.out 文件的大小一般要比 squshRootfs 小,如果 cowfile.out 被写满,根文件系统的读写操作将会出错,因此有必要给 cowfile.out 设置一个合理的大小以防止被写满。

由于 rootfs 是被 initrd 加载的,因此我们需要在 initrd 里面加入装载 rootfs 的代码。initrd 整个的执行过程是调用 /sbin/init 这个脚本文件,因此我们在这个脚本的最后加入以下代码逻辑即可。

注释:


1. dm-mirror 为 device mapper 工作所需要的驱动 

2. mknod: 创建一些设备文件,参数 1:设备文件名 参数 2:设备类型 参数 3:主设备号 参数 4:次设备号 

3. 将 squashRootfs 通过 loop 设备的形式挂载在目录 /realroot/mnt/ 下 

4. 将 /realroot/mnt/rootfs 设置为 loop 设备,并和 /dev/loop1 绑定 

5. "|"之前的部分是构建 dmsetup 的参数,其中 $(blockdev --getsize /dev/loop1) 表示创建镜像文件的大小,/dev/loop1 /dev/loop2 表示镜像文件是以 /realroot/mnt/rootfs 和 /realroot/mnt/cowfile.out 为蓝本进行创建的(在前面的操作中 loop1 和 loop2 分别进行了绑定操作)

清单 5. 构建可读写文件系统脚本
   # 加载驱动 ,参见注释 1
   modprobe dm-mirror 
   
   # 创建设备 ,参见注释 2
   mknod /dev/zero c 1 5 
   mknod /dev/loop0 b 7 0 
   mknod /dev/loop1 b 7 1 
   mknod /dev/loop2 b 7 2 
   mkdir /dev/cow 
   mknod /dev/cow/ctl b 241 255 
   mknod /dev/cow/0 b 241 0 
   
   # 挂载 squash 根文件系统,挂载完后您可以在 /realroot/mnt/ 下找到 rootfs 文件 ,参见注释 3
   mount /realroot/mnt/squashRootfs /realroot/mnt/ -o loop 
   
   # 设置 rootfs 为 loop 设备 ,参见注释 4
   losetup /dev/loop1 /realroot/mnt/rootfs 
   
   # 创建 cowfile.out 并挂载为 loop 设备,我们将来的写操作都会写入 cowfile.out 
   dd if=/dev/zero of=/realroot/mnt/cowfile.out bs=2K count=137500 
   losetup /dev/loop2 /realroot/mnt/cowfile.out 
   
   # 将 /realroot/mnt/rootfs 和 /realroot/mnt/cowfile.out 结合起来创建一个逻辑根文件设备,
   # 设备文件为 /dev/mapper/root_fs,,参见注释 5
   echo "0 $(blockdev --getsize /dev/loop1) snapshot /dev/loop1 /dev/loop2 p 64" | 
   dmsetup create root_fs 
   
   # 将上面创建的逻辑根文件设备 /dev/mapper/root_fs 挂载就可以看到一个可读写的根文件系统
   mount /dev/mapper/root_fs /realroot/mnt/Image 
   
   # 切换到最终可读写的根文件系统
   cd /realroot/mnt/Image 
   chroot ./sbin/init -i

加下来您就可以看到 rootfs 的所有内容,如图 4 所示:

图 4. 被挂载的根文件系统内容
aaa

还可以在这个文件系统中进行写操作,如图 5 所示:

图 5. 根文件系统的写操作
aaa

最重要的是 rootfs 没有被拷贝到内存中。

 

结束语

由于篇幅的限制,本文只给出了基本的描述。希望有更一步了解的读者可以通过对以下 linux 命令的学习来深入了解。

构建 Squash 压缩文件系统构所使用的主要命令:

  • mksquashfs:创建 Squash 压缩文件系统

使用 Squash 压缩文件系统构所使用的主要命令:

  • mknod:创建 Squash 压缩文件系统
  • losetup:设置并控制 Loop 设备
  • chroot:改变根目录
  • dmsetup:低水平逻辑卷管理

 

参考资料

学习

分享到:
评论

相关推荐

    构建嵌入式Linux的根文件系统.pdf

    【构建嵌入式Linux的根文件系统】 根文件系统是嵌入式Linux系统的核心组成部分,它包含了操作系统启动后运行的基本程序和服务。这篇文章主要探讨如何利用busybox来构建一个高效的、可定制的根文件系统。 Busybox是...

    创建和提取Squashfs文件系统的工具___下载.zip

    Squashfs是一种轻量级、高压缩率的文件系统,常用于嵌入式设备和Linux发行版中,以减少存储空间的需求。Squashfs文件系统的主要特点是它支持只读,这使得它非常适合用于软件镜像、固件更新以及在资源受限的环境中。 ...

    制作嵌入式linux文件系统(ramdisk,cramfs,squashfs).doc

    本篇文章将深入探讨三种常见的嵌入式Linux文件系统类型:ramdisk、cramfs和squashfs,以及如何构建一个包含所有必要文件的目录。 首先,让我们了解文件系统的基本概念。文件系统是磁盘驱动器或存储区域内的目录结构...

    squash文件系统打包和解包

    squash 文件系统在linux系统内编译成功了, 能生成打包和解包工具, 分享文件系统的属性

    嵌入式linux文件系统---很详细,非常适合初学者

    3. **ROM文件系统(如 squashfs, cramfs)**:这类文件系统被固化在只读存储器中,用于节省空间和保护系统文件不被修改。 4. **JFFS2 和 YAFFS**:这些是专门为闪存设备设计的文件系统,可以处理闪存的擦写限制。 ...

    SQUASHFS error问题解决

    错误信息 "SQUASHFS error: Unable to read metadata cache entry" 和 "SQUASHFS error: Unable to read inode" 进一步表明系统在尝试访问文件系统的元数据或索引节点时遇到了问题。 在分析这个问题时,我们需要...

    linux根文件系统制作

    通过理解Linux根文件系统的组织结构和初始化过程,开发者可以更有效地构建和优化针对特定硬件平台的嵌入式Linux系统,加速开发流程,提高系统性能和稳定性。遵循文件系统科学分类标准(FHS)可以使文件系统布局标准...

    squashfs-toos源码,可以在window上cygwin环境下进行编译,生成exe文件;测试可以正常使用

    Squashfs是一种轻量级、压缩的只读文件系统,常用于Linux发行版的嵌入式设备和Live CDs。它能够有效地减少存储空间的需求,提高系统运行效率。 在Windows环境下,通过Cygwin来编译和使用Squashfs-tools是可行的。...

    Linux下的flash文件系统的性能比较,jffs2,yaffs2,ubifs

    ### Linux下的Flash文件系统性能比较:jffs2、yaffs2与ubifs 在嵌入式系统中,选择适合的文件系统对于确保设备稳定运行至关重要。特别是针对基于闪存(Flash)存储介质的系统而言,文件系统的选择将直接影响到设备...

    squashfs-tools4.2源码包

    首先, squashfs-tools 4.2 提供了构建和管理 squashfs 文件系统的必备工具。其中,`mksquashfs` 是核心组件,它用于创建 squashfs 文件系统。用户可以将一个包含文件和目录的普通文件系统树压缩成一个单一的 ...

    squashfs-tools.zip

    Squashfs 是一种轻量级、压缩的文件系统,常用于嵌入式系统和Linux发行版的Live CDs。它的设计目标是提供高效的读取性能,同时占用极小的磁盘空间。Squashfs 工具包,如 "squashfs-tools.zip" 中所包含的,是一系列...

    为 ARM Linux 制作根文件系统

    在构建嵌入式 Linux 系统时,一个关键步骤是为 ARM 架构的设备创建根文件系统。根文件系统是 Linux 操作系统的核心组成部分,它包含了启动系统、运行基本服务以及提供用户接口所需的文件、目录和配置。下面将详细...

    Linux文件系统精通指南

    例如,使用 squashfs 或 cramfs 等压缩文件系统来节省空间,或构建只读文件系统以保持系统稳定性。 7. **ARM处理器**: ARM架构在嵌入式领域广泛使用,如6410型号是基于ARM9的处理器,适用于各种嵌入式设备,其Linux...

    如何制作嵌入式Linux文件系统

    嵌入式Linux文件系统是构建嵌入式设备操作系统核心的一部分,它决定了设备启动后如何管理和组织数据。文件系统不仅包括文件和目录的布局,还包括了权限控制、数据存储策略等关键元素。下面将详细介绍嵌入式Linux文件...

    linux_根文件系统_rootfs.pdf

    Linux 根文件系统 rootfs 详解 文件系统是指在一个磁盘(包括光盘、软盘、闪盘及其它存储...Linux 根文件系统 rootfs 是 Linux 系统中必不可少的组件,它提供了文件系统的基本结构和功能,是 Linux 系统的基础设施。

    Linux内核移植和根文件系统制作

    Linux内核移植和根文件系统制作是嵌入式Linux开发中的关键步骤,涉及到将Linux操作系统适配到特定硬件平台以及创建一个能支持系统运行的基本文件系统。以下是对这些知识点的详细说明: ### 第一部分:Linux内核移植...

    squashfs3.4.tar.gz

    Squashfs 是一种轻量级、高压缩率的文件系统,常用于Linux系统中的嵌入式设备和Live CD。在Squashfs3.4版本的压缩包"squashfs3.4.tar.gz"中,我们可以了解到这个版本的Squashfs具有多个关键特性和优势。以下是关于...

    squashfs4.2

    SquashFS是一种轻量级、高度压缩的只读文件系统,主要设计用于Linux内核。这个名为“squashfs4.2”的压缩包可能包含了SquashFS 4.2版本的相关源代码、编译工具、文档或者示例。在Linux环境中,SquashFS被广泛应用于...

    嵌入式 linux 根文件系统 rootfs.docx

    ### 嵌入式 Linux 根文件系统 RootFS 深度解析 #### 一、文件系统概述 文件系统(Filesystem)是操作系统用于管理存储设备(如硬盘、固态硬盘、USB闪存盘等)上的文件的一种逻辑结构。它不仅定义了文件如何存储、...

Global site tag (gtag.js) - Google Analytics