当前位置:首页 > 嵌入式 > Linux阅码场
[导读]本文以ext2文件系统为例来剖析一个真实的文件系统如何查找文件,这对于深入理解文件系统至关重要。1.准备文件系统镜像所用工具:dd、mkfs.ext2、hexdump、dumpe2fs、mount等工具1)制作100k大小镜像文件$ dd if=/dev/zero of=ext2...

本文以ext2文件系统为例来剖析一个真实的文件系统如何查找文件,这对于深入理解文件系统至关重要。

1.准备文件系统镜像

所用工具:dd、mkfs.ext2、hexdump、dumpe2fs、mount等工具

1)制作100k大小镜像文件

$ dd if=/dev/zero of=ext2.img bs=1k count=100
记录了100 0 的读入
记录了100 0 的写出
102400 bytes (102 kB, 100 KiB) copied, 0.00125457 s, 81.6 MB/s
2)格式化为ext2文件系统格式

$ mkfs.ext2 ext2.img
mke2fs 1.44.1 (24-Mar-2018)
丢弃设备块: 完成                            
创建含有 100 个块(每块 1k)和 16 个inode的文件系统

正在分配组表: 完成                            
正在写入inode表: 完成                            
写入超级块和文件系统账户统计信息: 已完成
3)查看文件系统信息

$ dumpe2fs ext2.img 
dumpe2fs 1.44.1 (24-Mar-2018)
Filesystem volume name:   
Last mounted on:          <not available>
Filesystem UUID:          3680e1d5-7f58-4324-9cbd-c7d382f0c3df
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              16
Block count:              100
Reserved block count:     5
Free blocks:              79
Free inodes:              5
First block:              1
Block size:               1024
Fragment size:            1024
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         16
Inode blocks per group:   2
Filesystem created:       Wed May 26 15:23:33 2021
Last mount time:          n/a
Last write time:          Wed May 26 15:23:33 2021
Mount count:              0
Maximum mount count:      -1
Last checked:             Wed May 26 15:23:33 2021
Check interval:           0 ()
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           128
Default directory hash:   half_md4
Directory Hash Seed:      5b0daa29-c2a0-4ab1-b09e-50992d3b070d


组 0:(块 1-99)
  主 超级块位于 1,组描述符位于 2-2
  块位图位于 3 ( 2)
  Inode 位图位于 4 ( 3)
  Inode表位于 5-6 ( 4)
  79 个可用 块,5 个可用inode,2 个目录 
  可用块数: 21-99
  可用inode数: 12-16

这实际是是读取文件系统的超级块和块组描述符信息。我们可以看的创建的文件系统的总体信息:

Filesystem magic number:0xEF53  表示为ext2文件系统Inode count:              16      表示文件系统inode个数为16Block count:              100 表示文件系统块个数为100 Free blocks:              79    表示文件系统空闲块个数为79Free inodes:              5        表示文件系统空闲inode个数为5 First block:              1           第一个数据块编号为1(编号0保留为引导块) Block size:               1024    文件系统块大小为1kBlocks per group:         8192 每个块组8192个块Inodes per group:         16 每个块组个inode Inode blocks per group:   2     每个块组2个inode块 First inode:          11   分配的第一个inode号为11(除根inode外,根inode号为2)Inode size:          128    inode大小为128字节块组的信息(这里只有一个块组)   1 - 99号 超级块块编号为 1     块组描述符块编号为  2 块位图块编号为 3      inode位图块编号为 4
inode表位于5和6块
79 个可用 块,5 个可用inode,2 个目录 (一个为根目录一个为lost found,存放坏块) 可用块数:21-99   可用inode数:12-164)挂载文件系统并创建文件

创建一个挂载点目录:
$  mkdir root_dir

挂载:
$  sudo mount -t ext2 ext2.img  root_dir

查看文件:
$ ls -la
总用量 17
drwxr-xr-x 3 root  root   1024 5月  26 15:23 .
drwxrwxr-x 3 hanch hanch  4096 5月  26 15:28 ..
drwx------ 2 root  root  12288 5月  26 15:23 lost found
可以发现有三个目录:

 .
 ..
 lost found
实际上是根目录的数据块的内容(包含各个目录项)。

下面我们来创建一个目录,目录下创建文件:

$ sudo mkdir dir

$ cd dir/
$ su
# echo hello > test.txt
现在目录树是这样的:

$ tree
.
├── dir
│   └── test.txt
└── lost found [error opening dir]

2 directories, 1 file
后面我们会通过解析文件系统镜像来观察如何查找  /dir/test.txt 文件的

现在关注一下相关的索引节点:

$ cd  dir

$ ls -lai
总用量 3
12 drwxr-xr-x 2 root root 1024 5月  26 15:57 .
 2 drwxr-xr-x 4 root root 1024 5月  26 15:56 ..
13 -rw-r--r-- 1 root root    6 5月  26 15:57 test.txt
可以发现 /dir目录下:当前工作目录下索引节点为12(dir目录的),上一级目录的索引节点为2(根目录),test.txt文件的所有节点为13。记住这几个索引节点后面我们会通过解析文件系统镜像来获得。

2.解析文件系统镜像

1)dump文件系统镜像

$ hexdump -C ext2.img

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  10 00 00 00 64 00 00 00  05 00 00 00 4f 00 00 00  |....d.......O...|
00000410  05 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000420  00 20 00 00 00 20 00 00  10 00 00 00 ae f8 ad 60  |. ... .........`|
00000430  ae f8 ad 60 01 00 ff ff  53 ef 00 00 01 00 00 00  |...`....S.......|
00000440  75 f7 ad 60 00 00 00 00  00 00 00 00 01 00 00 00  |u..`............|
...
*
00018c00  000 00 00 000 01 02  200 00 00 02 00 00 00  |................|
00018c10  000 02 02 2200 00  000 00 00 e8 03 08 01  |................|
00018c20  74 65 73 74 274 78 74  00 00 00 00 00 00 00 00  |test.txt........|
00018c30  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00019000
根据之前dumpe2fs的信息我们知道:

镜像文件中(均为16进制显示)

00000000 开始的1k大小  保留的引导块 

块1    00000400  开始的1k大小  保存磁盘的超级块 (dumpe2fs的部分信息从这里获得) 

块2     00000800   开始的1k大小  保存块组描述符    (dumpe2fs的部分信息从这里获得)

块3     00000c00 开始的1k大小  保存块位图  

块4     00001000    开始的1k大小   保存 Inode 位图  

块5 块6    00001400    开始的2k大小   保存 Inode表  

 剩下的为数据块

磁盘中的文件系统对象结构在内核如下文件定义:

fs/ext2/ext2.h

磁盘超级块:
 struct ext2_super_block {                                                 
         __le32  s_inodes_count;         /* Inodes count */                
         __le32  s_blocks_count;         /* Blocks count */
         __le32  s_r_blocks_count;       /* Reserved blocks count */
         __le32  s_free_blocks_count;    /* Free blocks count */
         __le32  s_free_inodes_count;    /* Free inodes count */
         __le32  s_first_data_block;     /* First Data Block */
         __le32  s_log_block_size;       /* Block size */
         __le32  s_log_frag_size;        /* Fragment size */
         __le32  s_blocks_per_group;     /* # Blocks per group */
         __le32  s_frags_per_group;      /* # Fragments per group */
         __le32  s_inodes_per_group;     /* # Inodes per group */
  ...
}

磁盘块组描述符:
struct ext2_group_desc                                                    
{
                                                                         
        __le32  bg_block_bitmap;                /* Blocks bitmap block */ 
        __le32  bg_inode_bitmap;                /* Inodes bitmap block */ 
        __le32  bg_inode_table;         /* Inodes table block */          
        __le16  bg_free_blocks_count;   /* Free blocks count */           
        __le16  bg_free_inodes_count;   /* Free inodes count */           
        __le16  bg_used_dirs_count;     /* Directories count */           
        __le16  bg_pad;                                                   
        __le32  bg_reserved[3];                                           
};                                                                        


磁盘inode:
 struct ext2_inode {                                                 
         __le16  i_mode;         /* File mode */                     
         __le16  i_uid;          /* Low 16 bits of Owner Uid */      
         __le32  i_size;         /* Size in bytes */                 
         __le32  i_atime;        /* Access time */                   
         __le32  i_ctime;        /* Creation time */                 
         __le32  i_mtime;        /* Modification time */             
         __le32  i_dtime;        /* Deletion Time */                 
         __le16  i_gid;          /* Low 16 bits of Group Id */       
         __le16  i_links_count;  /* Links count */                   
         __le32  i_blocks;       /* Blocks count */  
     ...
  __le32  i_block[EXT2_N_BLOCKS];/* Pointers to blocks */                
 ...
}; 


磁盘目录项:
struct ext2_dir_entry_2 {                                                    
        __le32  inode;                  /* Inode number */                   
        __le16  rec_len;                /* Directory entry length */         
        __u8    name_len;               /* Name length */                    
        __u8    file_type;                                                   
        char    name[];                 /* File name, up to EXT2_NAME_LEN */ 
};                                                                           

大家可以对照磁盘镜像文件和磁盘数据结构定义来解析出文件系统的超级块和块组描述符信息(可以发现和dumpe2fs工具显示的是一致的,例如镜像文件00000400 处四字节为10 00 00 00  是小端存储,所以为0x00000010=16);

3.路径名查找

下面开始我们的重头戏:查找文件系统中的  /dir/test.txt 文件

我们知道,使用文件系统给我最直观也是最大的好处是:用户可以通过一个路径名来访问文件,那么一个文件系统究竟如何来找到我们所需要的文件呢?下面我们详细来看ext2文件系统如何查找指定的文件的?(实际的内核中路径名查找比较复杂,考虑很多情况,如dentry cache查找、解析软链接文件、上级目录、挂载点等,当然如果目录分量是挂载点就会步进到相应文件系统的根目录,后面文件系统挂载专题会讲解,这里以简单的路径解析来让大家有个深刻的认识)。

1)查找根目录

万事开头难,对于访问一个目录上挂载的文件系统,内核路径名查找会判断并找到挂载的文件系统的根目录,这个过程在文件系统挂载的时候,会从磁盘上读取并在内存构建超级块实例,然后进行的最重要的一步是读取文件系统的根inode:

fs/ext2/super.c
ext2_fill_super
->root = ext2_iget(sb, EXT2_ROOT_INO)   //EXT2_ROOT_INO为2,系统定义好的
 ->raw_inode = ext2_get_inode(inode->i_sb, ino, 
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

Bitmap是一种通过位映射来高效存储和查询数据的技术,它在处理大规模数据集时能够有效地节省内存空间。Bitmap技术特别适用于需要对大量数据进行存在性检查的场景,比如用户签到、页面访问等,它可以显著节省内存空间。

关键字: IC设计 RAM bitmap

ABB变频器是工业自动化领域中广泛应用的电能控制设备,通过改变交流电机供电电源频率和电压来实现对电动机转速的精确调节。本文将详细阐述ABB变频器的基本结构、工作原理以及在不同应用场景中的关键技术。

关键字: abb 变频器

华盛顿2021年11月24日 /美通社/ -- Afiniti Ltd.(简称“Afiniti”)董事会任命Larry Babbio担任Afiniti董事会主席并立即生效。Babbio先生 自2016年以来一直...

关键字: ni abb

(全球TMT2021年11月24日讯)Afiniti Ltd.(简称“Afiniti”)董事会任命Larry Babbio担任Afiniti董事会主席并立即生效。Babbio自2016年以来一直担任Afiniti董事会...

关键字: Verizon ni abb

监控系统俗称「第三只眼」,几乎是我们每天都会打交道的系统,俗话说:无监控、不运维,监控系统的地位不言而喻。先来认识下主流的开源监控系统,Zabbix、Open-Falcon、Prometheus等,今天分享的资料包括【Z...

关键字: 监控系统 abb

在开始今天的文章之前,我先来请大家思考几个小问题。问1:我们在查看内核发送数据消耗的CPU时,是应该看sy还是si?问2:为什么你服务器上的/proc/softirqs里NET_RX要比NET_TX大的多的多?问3:发送...

关键字: 3g abb adv

Linux的内存管理可谓是学好Linux的必经之路,也是Linux的关键知识点,有人说打通了内存管理的知识,也就打通了Linux的任督二脉,这一点不夸张。有人问网上有很多Linux内存管理的内容,为什么还要看你这一篇,这...

关键字: abb

我们知道面向对象的三大特性分别是:封装、继承、多态。很多语言例如:C和Java等都是面向对象的编程语言,而我们通常说C是面向过程的语言,那么是否可以用C实现简单的面向对象呢?答案是肯定的!C有一种数据结构叫做结构体(st...

关键字: abb

临时变量目前遇到的一些产生临时变量的情况:函数实参、函数返回值、隐式类型转换、多余的拷贝。1.函数实参这点应该比较容易理解,函数参数,如果是实参传递的话,函数体里的修改并不会影响调用时传入的参数的值。那么函数体里操作的对...

关键字: abb

C20新增了两个const相关的关键字,于是当前存在四个相似的关键字:const,constexpr,consteval和constinit。接下来分别来进行讨论。第一,经过const修饰的变量具有只读属性,并且初始化发...

关键字: 5G abb
关闭