Linux系统编程第十一章学习笔记

前言

本章讨论EXT2文件系统。本章将引导大家实现一个完全与Linux兼容的EXT2文件系统。学会了这个就跟学会了C语言一样,属于是万物根源。
1

EXT2文件系统

1.EXT2文件系统

多年来,Linux一直使用EXT2 (Card等1995)作为默认文件系统。EXT3 (EXT3,
2014)是EXT2的扩展。EXT3中增加的主要内容是一个日志文件,它将文件系统的变更记录在日志中。日志可在文件系统崩溃时更快地从错误中恢复。没有错误的EXT3文件系统与EXT2文件系统相同。EXT3的最新扩展是EXT4 (Cao等2007 )。EXT4的主要变化是磁盘块的分配。在EXT4中,块编号为48位。EXT4不是分配不连续的磁盘块,而是分配连续的磁盘块区,称为区段。除了这些细微的更改之外,文件系统结构和文件操作保持不变。

2.EXT2文件系统数据结构

1.通过mkfs创建虚拟磁盘

mke2ds [-b blocksize -N ninoides] device nblocks

在设备上创建一个带有nblocks个块(每个块大小为blksize字节)和ninodes个索引节点的EXT2文件系统。设备可以是真实设备,也可以是虚拟磁盘文件。如果未指定blksize,则默认块大小为1KB。如果未指定ninoides, mke2fs 将根据nblocks计算一个默认的ninodes数。得到的EXT2文件系统可在Linux中使用。
如下实操

dd if=/dev/zero of=vdisk bs=1024 count=1440
mke2fs vdisk 1440

可在一个名为vdisk的虚拟磁盘文件上创建-一个EXT2文件系统,有1440个大为1KB的块。
2

2.虚拟磁盘布局

上述EXT2文件系统的布局如下图所示
3
Block#0:引导块B0 是引导块,文件系统不会使用它。它用来容纳一个引导程序,从磁盘引导操作系统。

3.超级块

Block#1 :超级块(在硬盘分区中字节偏移量为1024) B1 是超级块,用于容纳整个文件系统的信息。下文说明了超级块结构中的一些重要字段。

struct ext2_buper_block {
u32 s_inodes_count;/* Inodes count */
u32 s_blocks_count;/* B1ocks count */
u32 s_r_blocks_count;/* Reserved blocks count */
u32 s_free_blocks_count;/* Free blocks count */
u32 s_free_inodes_count;/* Free inodes count */
u32 s_first_ data_ block;/* First Data Block */
u32 s_1og_ _block_ .size;/* Block size */
u32 s_1og_ cluster_ size;/* Allocation cluster size */
u32 s_blocks_ per_ group ;/* # Blocks per group */
u32 s_clusters_ per_ group; /* # Fragments per group */
u32 s_inodes_ per_ group ;/* # Inodes per group */
u32 s_mtime;/* Mount time */
u32 s_wtime;/* Write time */
u16 s_Jont_ count;/* Mount count. */
s16 s_max_ mnt_ count;/* Maximal mount count */
u16 s_magici/* Magic signature */
// more non-essential fields :
u16 s_ inode_ size;/* size of inode structure */
}

s_ first _data_block: 0表示4KB块大小,1表示1KB块大小。它用于确定块组描述符的起始块,即s_ first_ data_ block + 1。
s_ log_ block_ size: 确定文件块大小,为1KB*(2**s_log_block gsize), 例如: 0表示1KB块大小,1表示2KB块大小,2表示4KB块大小等。最常用的块大小是用于小文件系统的1KB和用于大文件系统的4KB。
s_ mnt_ count:已挂载文件系统的次数。当挂载计数达到max_mnt count时,fsck 会话将被迫检查文件系统的一致性。
s_magic: 标识文件系统类型的幻数。EXT2/3/4 文件系统的幻数0xEF53。

4.块组描述符

Block#2:块组描述符块(硬盘上的s_ first_ data_ block+1 ) EXT2 将磁盘块分成几个组。每个组有8192个块(硬盘上的大小为32K)。每组用一个块组描述符结构体来描述。

struct ext2_ group_ desc {
u32 bg_ ,block_ _bi tmap;// Bmap block number
u32 bg_ inode_ bi tmap;// Imap block number
u32 bg_ inode_ table;// Inodes begin block number
u16 bg_ free_ blocks_ count;// THESE are OBVIOUS
u16 bg_ free_ inodes_ count ;
u16 bg_ _used_ dirs_ count;
u16 bg_ pad;// ignore these
u32 bg_ reserved[3] ;

由于一个虚拟软盘(FD)只有1440个块,B2就只包含一个块组描述符。其余的都是0。在有大量块组的硬盘上,块组描述符可以跨越多个块。块组描述符中最重要的字段是bg_block_ bitmap、 bg inode_ bitmap 和bg. inode table, 它们分别指向块组的块位图、索引节点位图和索引节点起始块。对于Linux格式的EXT2文件系统,保留了块3到块7。所以,bmap=8,imap=9,inode_ table= 10。

5.块和索引节点位图

Block#8:块位图(Bmap)(bg block bitmap)位图是用来表示某种项的位序列,例如磁盘块或索引节点。位图用于分配和回收项。在位图中,0位表示对应项处于FREE状态,1位表示对应项处于IN_USE状态。一个软盘有1440个块,但是Block#0未被文件系统使用。所以,位图只有1439个有效位。无效位被视作IN USE,设置为1。
Block#9:索引节点位图(Imap) ( bg. jinode
bitmap) 一个索引节点就是用来代表一一个文件的数据结构。EXT2文件系统是使用有限数量的索引节点创建的。各索引节点的状态用B9的Imap中的一个位表示。在EXT2 FS中,前10个索引节点是预留的。所以,空EXT2FS的Imap以10个1开头,然后是0。无效位再次设置为1。

6.索引节点

Block#10:索引(开始)节点(bg_ inode_ table) 每个文件都用一个128字节(EXT4中是256字节)的唯一索引节点结构体表示。下面列出了主要索引节点字段。

struct ext2_ inode {
u16 i_ mode;// 16 bits = |tttt |ugs |rwx |rwx | rWx |
u16 i_uid;// owner uid
u32 i_ size;//file size in bytes
u32 i_ atime;// tine fields in seconds
u32 i_ ctime;// since 00:00:00.1-1-1970
u32 i_ mtime;
u32 i_ dt ime;
u16 i_ gid;// group ID
u16 i_ links_ count; // hard-link count
u32 i_ blocks;// number of 512-byte sectors
u32 i_ flags;// IGNORE
u32 i_ reserved1 ;// IGNORE
u32 i_ _block[15] ;// See details below
u32 i_ pad[7];// for inode size = 128 bytes

在索引节点结构体中,i _mode为u16或2字节无符号整数。
4
在i mode字段中,前4位指定了文件类型,例如: tt=1000表示REG文件,0100表示DIR文件等。接下来的3位ugs表示文件的特殊用法。最后9位是用于文件保护的rwx权限位。
i_size字段表示文件大小(以字节为单位)。各时间字段表示自1970年1月1日0时0分0秒以来经过的秒数。所以,每个时间字段都是一个非常大的无符号整数。
如下图所示:
5
6


i blocek[15]数组包含指向文件磁盘块的指针,这些磁盘块有:
直接块: i _block[0]至i block[1], 指向直接磁盘块。
间接块: i _block[12]指向一个包含256个块编号(对于1KB BLKSIZE)的磁盘块,每个块编号指向-一个磁盘块。
双重间接块: i block[13]指向一个指向256个块的块,每个块指向256个磁盘块。
三重间接块: i _block([14] 是三重间接块。对于“小型”EXT2 文件系统,可以忽略它。索引节点大小(128或256)用于平均分割块大小(1KB或4KB),所以,每个索引节点块都包含整数个索引节点。在简单的EXT2文件系统中,索引节点的数量是184个(Linux默认值)。索引节点块数等于184/8-23个。因此,索引节点块为B10至B32。每个索引节点都有一个唯一的索引节点编号,即索引节点在索引节点块上的位置+1。注意,索引节点位置从0开始计数,而索引节点编号从1开始计数。0索引节点编号表示没有索引节点。根目录的索引节点编号为2。同样,磁盘块编号也从1开始计数,因为文件系统从未使用块0。块编号0表示没有磁盘块。

7.数据块

紧跟在索引节点块后面的是文件存储数据块。假设有184个索引节点,第一个实际数据块是B33,它就是根目录/的i _block[0]。

8.目录条目

目录包含dir_entry结构,即

struct ext2_ dir_ entry_ _2{
u32 inode;// inode number; count from 1, NOT 0
u16 rec_ len;// this entry's length in bytes
u8 name_ len;// name length in bytes
u8 file_ type;// not used
char name[EXT2_ NAME LEN]; // name: 1-255 chars, no ending NULL
);

dir_entry是一种可扩充结构。名称字段包含1到255个字符,不含终止NULL。所以dir_entry 的rec_len 也各不相同。
相信学到这里,你已经对EXT2系统有了一个结构性的理解了,接下来自己去试试吧!

苏格拉底挑战

EXT2文件系统数据结构知识点
posted @ 2023-10-14 14:35  20211120  阅读(85)  评论(0编辑  收藏  举报