第11章 EXT2文件系统
摘要
EXT2文件系统在Linux中的历史地位以及EXT3/EXT4文件系统的当前状况;
用编程示例展示了各种EXT2数据结构以及如何遍历EXT2文件系统树;
实现支持Linux内核中所有文件操作的EXT2文件系统;展示了如何通过虚拟磁盘的 mountroot来构建基本文件系统;
将文件系统的实现划分为3个级别,级别1扩展了基本文件系统,以实现文件系统树,级别2实现了文件内容的读/写操作,级别3实现了文件系统的挂载/装载和文件保护;
描述了各个级别文件系统函数的算法,并通过编程示例演示了它们的实现过程;
EXT2文件系统
EXT2即第二代扩展文件系统(英语:second extended filesystem,缩写为 EXT2)
EXT2文件系统数据结构
通过mkfs创建虚拟磁盘
dd if=/dev/zero of=vdisk bs=1024 count=1440
mke2fs vdisk 1440
虚拟磁盘布局
Block#0 是引导块,文件系统不会使用它,它用于容纳从磁盘引导操作系统的引导程序
超级块
Block#1 是超级块,用于容纳关于整个文件系统的信息
块组描述符
Block#2 是块组描述符,EXT2将磁盘块分成几个组,每组有8192个块,每组用一个块组描述符结构体描述
块和索引节点位图
Block#8 是块位图,用于表示某种项的位序列,例如磁盘块或索引节点,位图用于分配和回收项。
Block#9 是索引节点位图,索引节点用于代表一个文件的数据结构
索引节点
Block#10 是索引(开始)节点块,索引节点大小用于平均分割块大小,所以每个索引节点块都包含整数个索引节点。
i_mode为U16或2字符无符号整数
i_block[15]数组包含指向文件磁盘的指针,这些磁盘块有:
直接块:iblock[0]至i_block[11],指向直接磁盘块。
间接块:iblock[12]指向一个包含256个块编号(对于1KBBLKSIZE)的磁盘块,每个块编号指向一个磁盘块。
双重间接块:iblock[13]指向一个指向256个块的块,每个块指向256个磁盘块。
三重间接块:iblock[14]是三重间接块。对于“小型”EXT2文件系统,可以忽略它。
数据块
是紧跟在索引节点块后面的文件存储块
目录条目
包含dir_entry结构()一种可扩充结构,即
struct ext2_dir_entry_2{
u32 inode;
u16 rec_len;
u8 name_len;
u8 file_type;
char name[EXT2_NAME_LEN];
};
/*********** superblock.c program ************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/io.h>
#include <ext2fs/ext2_fs.h>
// typedef u8, ul6, u32 SUPER for convenience typedef typedef typedef
typedef unsigned char u8;
typedef unsigned short ul6;
typedef unsigned int u32;
typedef struct ext2_super_block SUPER;
SUPER *sp;
char buf[1024];
int fd, blksize, inodesize;
int print(char *s, u32 x)
{
printf("%-30s = %8d\n", s, x);
}
int super(char *device)
{
fd = open(device, O_RDONLY);
if (fd < 0)
{
printf("open %s failed\n", device);
exit(1);
}
lseek(fd, (long)1024*1, 0); // block 1 or offset 1024
read(fd, buf, 1024);
sp = (SUPER *)buf; // as a super block structure
// check for EXT2 FS magic number
printf("%-30s = %8x ", "s_magic", sp->s_magic);
if (sp->s_magic != 0xEF53)
{
printf("NOT an EXT2 FS\n"); exit(2);
}
printf("EXT2 FS OK\n");
print("s_inodes_count", sp->s_inodes_count);
print("s_blocks _count", sp->s_blocks_count);
print("s_r_blocks_count", sp->s_r_blocks_count);
print("s_free_inodes_count", sp->s_free_inodes_count);
print("s_free_blocks_count", sp->s_free_blocks_count);
print("s_first_data_blcok", sp->s_first_data_block);
print("s_log_block_s i z e", sp->s_log_block_size);
print("s_blocks_per_group", sp->s_blocks_per_group);
print("s_inodes_per_group", sp-> s_inodes_per_group);
print("s_mnt_count", sp->s_mnt_count);
print("s_max_mnt_count", sp-> s_max_mnt_count);
printf("%-30s = %8x\n", "s_magic", sp->s_magic);
printf ("s_mtime = %s\n", ctime ((const time_t *)&sp->s_mtime));
printf ("s_wtime = %s", ctime ((const time_t *)&sp->s_wtime));
blksize = 1024 * (1 << sp->s_log_block_size);
printf("block size = %d\n", blksize);
printf("inode size = %d\n", sp->s_inode_size);
}
char *device = "vdisk"; // default device name
int main(int argc, char *argv[])
{
if (argc>1)
device = argv[1];
super(device);
}
运行
邮差算法
邮差算法是指将一个二元(多元)应表转换为一个一元的线性表的转换算法
遍历EXT2文件系统书
遍历算法
读取超级块。
检査幻数s_magic ( OxEF53 ),验证它确实是EXT2 FS,
读取块组描述符块(1 + s_first_data_block)
以访问组0描述符。从块组描述符的bg_inode_table条目中找到索引节点的起始块编号,并将其称为InodesBeginBlock,
读取InodeBeginBlock,获取/的索引节点,即INODE #2。
将路径名标记为组件字符串
假设组件数量为n,例如,如果路径名=/a/b/c,则组 件字符串是“a”“b”“c”,其中n = 3。用name[0], namefl],…,name[n-l]来表示组件。
从(3)中的根索引节点开始,在其数据块中搜索name[0]。
使用索引节点号ino来定位相应的索引节点。
ino从1开始计数,使用邮差算法计算包含索引节点的磁盘块及其在该块中的偏移量。
问题:ext2头文件的缺失以及下载,按照书上提供方法sudo apt-get install ext2fs-dev无法解决,包不存在,且使用apt-get sudo 之后任然无法解决问题
解决:使用sudo apt-get isntall libext2fs-dev成功解决问题