当前位置:首页 > 嵌入式 > 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, 
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭