百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

文件系统(十一):Linux Squashfs只读文件系统介绍

liuian 2025-02-07 18:19 20 浏览

liwen01 2024.07.21

前言

嵌入式Linux系统中,squashfs文件系统使用非常广泛。它主要的特性是只读,文件压缩比例高。对于flash空间紧张的系统,可以将一些不需要修改的资源打包成压缩的只读文件系统格式,从而达到节省空间的目的。

另外还有个特性就是它可以分块解压缩,使用数据会更加灵活,但同时也会引入读放大的问题。

(一)制作squash文件系统

使用mksquashfs可以将文件及文件夹制作成squash文件系统镜像文件,比如我们要将squashfs-root文件夹打包成squashfs镜像文件,可以使用命令:

mksquashfs squashfs-root squashfs-root.sqsh -comp xz

这里是使用xz压缩方式进行文件压缩

(1)压缩比例测试

squashfs是一个只读压缩的文件系统,我们简单测试一下它的压缩功能

使用/dev/zero生成零数据写入到文件夹squashfs_zero对应的文件中

dd if=/dev/zero of=file1 bs=256K count=1

制作如下测试文件目录及测试文件:

biao@ubuntu:~/test/squashfs/squashfs_zero$ tree
.
├── test1
│   ├── file1
│   ├── file1_1
│   └── file1_2
├── test2
│   ├── file2
│   ├── file2_1
│   └── file2_2
├── test3
│   ├── file3
│   ├── file3_1
│   └── file3_2
└── test4
    ├── file4
    ├── file4_1
    └── file4_2

4 directories, 12 files
biao@ubuntu:~/test/squashfs/squashfs_zero$

文件大小如下:

biao@ubuntu:~/test/squashfs/squashfs_zero$ du -h
1.5M    ./test3
2.1M    ./test2
2.1M    ./test1
1.7M    ./test4
7.3M    .
biao@ubuntu:~/test/squashfs/squashfs_zero$

使用xz压缩方式将squashfs_zero制作成镜像文件

mksquashfs squashfs_zero squashfs_zero.sqsh -comp xz

文件大小如下:

biao@ubuntu:~/test/squashfs$ ll -h squashfs_zero.sqsh 
-rw-r--r-- 1 biao biao 4.0K Jun 26 23:48 squashfs_zero.sqsh
biao@ubuntu:~/test/squashfs$

这里是将7.3M大小squashfs_zero文件夹压缩成了一个4k大小的squashfs_zero.sqsh。当然,这里的测试是非常极端的,因为文件写入的数据都是0,如果写入随机数那压缩比例就会相差非常大了。

(二)squashfs数据分析

(1)数据布局

Squashfs的一个镜像文件它最多包含下面9个部分:Superblock、Compression options、Data blocks fragments、Inode table、Directory table、Fragment table、Export table、 UID/GID lookup table、Xattr table。

最多包含的意思,也就是有些部分不是必须的,比如Compression options 部分。

它们在镜像文件中的数据分布如下图:

(2)制作测试镜像文件

使用/dev/urandom 生成随机数写到文件夹squashfs_urandom对应的文件:

dd if=/dev/urandom of=filex bs=10K count=50

制作如下测试文件目录及测试文件:

biao@ubuntu:~/test/squashfs/squashfs_urandom$ tree
.
├── test1
│   ├── file1
│   ├── file1_1
│   └── file1_2
├── test2
│   ├── file2
│   ├── file2_1
│   └── file2_2
├── test3
│   ├── file3
│   ├── file3_1
│   └── file3_2
└── test4
    ├── file4
    ├── file4_1
    └── file4_2

4 directories, 12 files
biao@ubuntu:~/test/squashfs/squashfs_urandom$

squashfs 文件系统的组成部分,大部分也都是压缩的,为了我们后面的数据分析,我们设置Data blocks fragments、Inode table、Directory table、Fragment table不进行压缩

制作命令如下:

mksquashfs squashfs_urandom squashfs_urandom.sqsh -comp xz  -noF -noX -noI -noD

(3)查看镜像数据信息

如果要查看squashfs的概要信息,可以使用unsquashfs命令进行查看

unsquashfs -s squashfs_urandom.sqsh

输出内容信息如下:

biao@ubuntu:~/test/squashfs$ unsquashfs -s squashfs_urandom.sqsh 
Found a valid SQUASHFS 4:0 superblock on squashfs_urandom.sqsh.
Creation or last append time Wed Jun 26 23:28:18 2024
Filesystem size 5032.60 Kbytes (4.91 Mbytes)
Compression xz
Block size 131072
Filesystem is exportable via NFS
Inodes are uncompressed
Data is uncompressed
Fragments are uncompressed
Always-use-fragments option is not specified
Xattrs are uncompressed
Duplicates are removed
Number of fragments 2
Number of inodes 37
Number of ids 1
biao@ubuntu:~/test/squashfs$

这里我们可以看到,上面我们设置-no的部分,是没有进行数据压缩的。

(4)Superblock参数分析

Superblock 在镜像文件的最开始位置,大小固定为96个字节,查看数据内容如下:

biao@ubuntu:~/test/squashfs$ hexdump  -s 0 -n 96 -C squashfs_urandom.sqsh 
00000000  68 73 71 73 11 00 00 00  ec 5c 7a 66 00 00 02 00  |hsqs.....\zf....|
00000010  02 00 00 00 04 00 11 00  cb 01 01 00 04 00 00 00  |................|
00000020  ac 02 00 00 00 00 00 00  16 9d 4e 00 00 00 00 00  |..........N.....|
00000030  0e 9d 4e 00 00 00 00 00  ff ff ff ff ff ff ff ff  |..N.............|
00000040  60 98 4e 00 00 00 00 00  2e 9b 4e 00 00 00 00 00  |`.N.......N.....|
00000050  6e 9c 4e 00 00 00 00 00  00 9d 4e 00 00 00 00 00  |n.N.......N.....|
00000060
biao@ubuntu:~/test/squashfs$

对Superblock的数据进行解析

这里我们看到几个比较关键的数据

  1. 最开始的4个字节为squashfs的magic,值为hsqs
  2. block size 是每个数据块的最大长度,这里是128KB,squashfs支持的块大小范围是:4KB~1MB
  3. compressor 表示压缩类型,这里的4表示xz压缩,其它还支持GZIP、LZMA、LZO、LZ4、ZSTD 数据压缩格式。
  4. frag count 表示有多少段数据是存储在fragments组块中
  5. 最后面是各个table组块的开始位置

(5)inode table数据分析

从superblock中我们知道inode table的开始位置是在0x4e9860位置

biao@ubuntu:~/test/squashfs$ hexdump  -s 0x4e9860 -n 718 -C squashfs_urandom.sqsh     
004e9860  cc 82 02 00 b4 01 00 00  00 00 9b e9 78 66 02 00  |............xf..|
004e9870  00 00 60 00 00 00 ff ff  ff ff 00 00 00 00 00 20  |..`............ |
004e9880  03 00 00 00 02 01 00 20  01 01 02 00 b4 01 00 00  |....... ........|
004e9890  00 00 c3 e9 78 66 03 00  00 00 60 20 03 00 ff ff  |....xf....` ....|
004e98a0  ff ff 00 00 00 00 00 d0  07 00 00 00 02 01 00 00  |................|
004e98b0  02 01 00 00 02 01 00 d0  01 01 02 00 b4 01 00 00  |................|
004e98c0  00 00 cf e9 78 66 04 00  00 00 60 f0 0a 00 ff ff  |....xf....`.....|
004e98d0  ff ff 00 00 00 00 00 80  0c 00 00 00 02 01 00 00  |................|
004e98e0  02 01 00 00 02 01 00 00  02 01 00 00 02 01 00 00  |................|
004e98f0  02 01 00 80 00 01 01 00  fd 01 00 00 00 00 b1 e9  |................|
004e9900  78 66 01 00 00 00 00 00  00 00 02 00 00 00 3a 00  |xf............:.|
004e9910  00 00 11 00 00 00 02 00  b4 01 00 00 00 00 f9 e9  |................|
004e9920  78 66 06 00 00 00 00 00  00 00 00 00 00 00 00 00  |xf..............|
004e9930  00 00 00 78 00 00 02 00  b4 01 00 00 00 00 01 ea  |...x............|
004e9940  78 66 07 00 00 00 00 00  00 00 00 00 00 00 00 78  |xf.............x|
004e9950  00 00 00 18 01 00 02 00  b4 01 00 00 00 00 08 ea  |................|
004e9960  78 66 08 00 00 00 00 00  00 00 01 00 00 00 00 00  |xf..............|
004e9970  00 00 00 f0 00 00 01 00  fd 01 00 00 00 00 ea e9  |................|
.........
.........
biao@ubuntu:~/test/squashfs$

对数据进行分析

这里有几个参数需要注意:

(a)inode_type

inode_type 是inode的类型,数值2表示普通文件,其它类型定义如下:

(b)block_sizes

这里是描述的块的大小(有可能是压缩的),这个大小需要解析。

为什么有些inode有多个block_sizes呢?这个是因为superblock中定义了一个block的最大值,如果一个文件的大小大于block最大值,那它就存在多个block_sizes。

实际每一个文件都有一个对应的inode,它都是按序分布在inode table中。

(6)directory table 数据分析

从superblock中我们知道directory table的开始位置是在0x4e9b2e位置:

biao@ubuntu:~/test/squashfs$ hexdump  -s 0x4e9b2e -n 320 -C squashfs_urandom.sqsh          
004e9b2e  1c 81 02 00 00 00 00 00  00 00 02 00 00 00 00 00  |................|
004e9b3e  00 00 02 00 04 00 66 69  6c 65 31 28 00 01 00 02  |......file1(....|
004e9b4e  00 06 00 66 69 6c 65 31  5f 31 58 00 02 00 02 00  |...file1_1X.....|
004e9b5e  06 00 66 69 6c 65 31 5f  32 02 00 00 00 00 00 00  |..file1_2.......|
004e9b6e  00 06 00 00 00 b4 00 00  00 02 00 04 00 66 69 6c  |.............fil|
004e9b7e  65 32 d4 00 01 00 02 00  06 00 66 69 6c 65 32 5f  |e2........file2_|
004e9b8e  31 f4 00 02 00 02 00 06  00 66 69 6c 65 32 5f 32  |1........file2_2|
004e9b9e  02 00 00 00 00 00 00 00  0a 00 00 00 34 01 00 00  |............4...|
004e9bae  02 00 04 00 66 69 6c 65  33 68 01 01 00 02 00 06  |....file3h......|
004e9bbe  00 66 69 6c 65 33 5f 31  98 01 02 00 02 00 06 00  |.file3_1........|
004e9bce  66 69 6c 65 33 5f 32 02  00 00 00 00 00 00 00 0e  |file3_2.........|
004e9bde  00 00 00 f8 01 00 00 02  00 04 00 66 69 6c 65 34  |...........file4|
004e9bee  28 02 01 00 02 00 06 00  66 69 6c 65 34 5f 31 60  |(.......file4_1`|
004e9bfe  02 02 00 02 00 06 00 66  69 6c 65 34 5f 32 03 00  |.......file4_2..|
004e9c0e  00 00 00 00 00 00 01 00  00 00 94 00 00 00 01 00  |................|
004e9c1e  04 00 74 65 73 74 31 14  01 04 00 01 00 04 00 74  |..test1........t|
004e9c2e  65 73 74 32 d8 01 08 00  01 00 04 00 74 65 73 74  |est2........test|
004e9c3e  33 8c 02 0c 00 01 00 04  00 74 65 73 74 34 20 80  |3........test4 .|
004e9c4e  60 70 17 00 00 00 00 00  00 90 01 01 00 00 00 00  |`p..............|
004e9c5e  60 a8 4d 00 00 00 00 00  00 f0 00 01 00 00 00 00  |`.M.............|
004e9c6e
biao@ubuntu:~/test/squashfs$

对数据进行解析:

这里最开始是一个directory header结构,它由count、start、inode number组成,它们定义如下:

每个directory header 至少需要携带一个Directory Entry,Directory Entry的定义如下:

这里的inode number 与 inode table 中的inode number是相互对应的

(7)Data blocks fragments 分析

(a)Data blocks

在我们测试的这个镜像文件中,应为使用的是xz压缩方式,属于常规压缩方式,Compression options中不会有描述,也就是说Compression options组成部分是为空。

在Superblock后面紧接着的就是Data blocks数据。

从inode table和dir table我们知道,最开始存储的是inode number为2的file1 文件。

因为我们这里的数据未进行压缩,正常应该是对比镜像文件0x60地址开始的数据与file1文件开始的数据一样的。

(b)fragments

fragments 组块设计的目的是用来存储一些小文件,将它们组合成一个block来存储,还有一种就是前面文件剩余的一小部分数据,也有可能会被存储在fragments组块中。

具体哪些数据存储到了fragments,可以查看fragments table表

(三)squashfs工作原理

(1)挂载文件系统

squashfs被挂载的时候,系统首先读取superblock块,获取squashfs基本信息和各个表格的位置。

(2)访问文件或目录

  • 系统从 superblock 获取 inode table 和 directory table 的位置。
  • 如果是访问目录,系统查找 directory table,获取目录中每个文件和子目录的名称及其 inode 编号。
  • 通过 inode 编号,从 inode table 获取文件或目录的 inode,了解文件的元数据和数据块位置。
  • 对于小文件或大文件的片段,通过 inode 中的信息查找 fragment table,获取片段的数据位置。

(四)squashfs优缺点

(1)优点

高压缩率:SquashFS 使用 gzip、lzma、lz4、xz 等压缩算法,能够显著减少文件系统的大小,节省存储空间。

只读特性:适合用于需要保护数据完整性的环境,如嵌入式系统和操作系统的只读镜像。

高效的随机访问:SquashFS 支持高效的随机读取访问,适合读取频繁的场景。

碎片处理: 通过 Fragment Table,SquashFS 能有效处理小文件,减少存储碎片,提高存储效率。

存储和性能优化: 支持文件、目录和 inode 的压缩,减少了存储占用和 I/O 操作,提高了性能。

数据完整性:SquashFS 可以包含校验和,用于确保数据的完整性和防止数据损坏。

(2)缺点

只读特性:SquashFS 是只读的,不能直接修改文件系统中的文件或目录。这意味着需要更新或更改文件系统时,必须重新生成整个文件系统镜像。

压缩开销:虽然读取速度较快,但解压缩过程仍然需要一定的 CPU 资源。在低性能的嵌入式系统中,这可能会对系统性能产生一定影响。

内存消耗:在读取大文件时,解压缩过程可能会消耗大量内存,尤其是在资源受限的嵌入式系统中,这可能会成为一个瓶颈

结尾

上面介绍了squashfs文件系统的数据组成和它们相互工作的原理以及squash文件系统的优缺点。

这里提一个问题:如果根文件系统使用squashfs文件系统,main执行文件也位于根文件系统中,在不考虑双分区备份升级的情况下,要怎么升级根文件系统?

在main程序中直接将新squashfs镜像文件写入到根文件系统所在的mtdblock中是否可以?会不会存在根文件系统更新异常的风险?

-------------------End-------------------

如需获取更多内容

请关注 liwen01 公众号

相关推荐

python入门到脱坑函数—定义函数_如何定义函数python

Python函数定义:从入门到精通一、函数的基本概念函数是组织好的、可重复使用的代码块,用于执行特定任务。在Python中,函数可以提高代码的模块性和重复利用率。二、定义函数的基本语法def函数名(...

javascript函数的call、apply和bind的原理及作用详解

javascript函数的call、apply和bind本质是用来实现继承的,专业点说法就是改变函数体内部this的指向,当一个对象没有某个功能时,就可以用这3个来从有相关功能的对象里借用过来...

JS中 call()、apply()、bind() 的用法

其实是一个很简单的东西,认真看十分钟就从一脸懵B到完全理解!先看明白下面:例1obj.objAge;//17obj.myFun()//小张年龄undefined例2shows(...

Pandas每日函数学习之apply函数_apply函数python

apply函数是Pandas中的一个非常强大的工具,它允许你对DataFrame或Series中的数据应用一个函数,可以是自定义的函数,也可以是内置的函数。apply可以作用于DataF...

Win10搜索不习惯 换个设定就好了_window10搜索用不了怎么办

Windows10的搜索功能是真的方便,这点用惯了Windows10的小伙伴应该都知道,不过它有个小问题,就是Windows10虽然会自动联网搜索,但默认使用微软自家的Bing搜索引擎和Edge...

面试秘籍:call、bind、apply的区别,面试官为什么总爱问这三位?

引言你有没有发现,每次JavaScript面试,面试官总爱问你call、bind和apply的区别?好像这三个方法成了通关密码,掌握了它们,就能顺利过关。其实不难理解,面试官问这些问题,不...

记住这8招,帮你掌握“追拍“摄影技法—摄影早自习第422日

杨海英同学提问:请问叶梓老师,我练习追拍时,总也不能把运动的人物拍清晰,速度一般掌握在1/40-1/60,请问您如何把追拍拍的清晰?这跟不同的运动形式有关系吗?请您给讲讲要点,谢谢您!摄影:Damia...

[Sony] 有点残酷的测试A7RII PK FS7

都是好机!手中利器!主要是最近天天研究fs5,想知道fs5与a7rii后期匹配问题,苦等朋友的fs5月底到货,于是先拿手里现有的fs7小测一下,十九八九也能看到fs5的影子,另外也了解一下fs5k标配...

AndroidStudio_Android使用OkHttp发起Http请求

这个okHttp的使用,其实网络上有很多的案例的,但是,如果以前没用过,copy别人的直接用的话,可以发现要么导包导不进来,要么,人家给的代码也不完整,这里自己整理一下.1.引入OkHttp的jar...

ESL-通过事件控制FreeSWITCH_es事务控制

通过事件提供的最底层控制机制,允许我们有效地利用工具箱,适时选择使用其中的单个工具。FreeSWITCH是一个核心交换与混合矩阵,它周围有几十个模块提供各种功能特性。我们完全控制了所有的即时信息,这些...

【调试】perf和火焰图_perf生成火焰图

简介perf是linux上的性能分析工具,perf可以对event进行统计得到event的发生次数,或者对event进行采样,得到每次event发生时的相关数据(cpu、进程id、运行栈等),利用这些...

文本检索控件也玩安卓?dtSearch Engine发布Android测试版

dtSearchEngineforLinux(原生64-bit/32-bitC++和JavaAPIs)和dtSearchEngineforWin&.NET(原生64-bi...

网站后台莫名增加N个管理员,记一次SQL注入攻击

网站没流量,但却经常被SQL注入光顾。最近,网站真的很奇怪,网站后台不光莫名多了很多“管理员”,所有的Wordpres插件还会被自动暂停,导致一些插件支持的页面,如WooCommerce无法正常访问、...

多元回归树分析Multivariate Regression Trees,MRT

多元回归树(MultivariateRegressionTrees,MRT)是单元回归树的拓展,是一种对一系列连续型变量递归划分成多个类群的聚类方法,是在决策树(decision-trees)基础...

JMETER性能测试_JMETER性能测试指标

jmeter为性能测试提供了一下特色:jmeter可以对测试静态资源(例如js、html等)以及动态资源(例如php、jsp、ajax等等)进行性能测试jmeter可以挖掘出系统最大能处...