《Linux/Unix系统编程》第十一章读书笔记

EXT2文件系统

EXT2文件系统

多年来,Linux一直使用EXT2作为默认文件系统。

EXT3相对于2,主要增加了一个日志文件;

EXT4相对于3,主要是磁盘块的分配。

 

EXT2文件系统数据结构

mkfs创建虚拟磁盘

mke2fs [-b blksize -N ninodes] device nblocks

创建了一个带有nblocks个块(每个块大小blksize字节)和ninodes个索引节点的EXT2文件系统。

虚拟磁盘布局

  • Block#0:引导块文件系统不会使用它,用来容纳一个引导程序,从磁盘引导操作系统

  • Block#1:超级块,用于容纳整个文件系统的信息。 部分重要字段:

    struct ext2_super_block { u32 s_inodes_count; // Inodes count u32 s_blocks_count; // Blocks 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_log_block_size; // Block size u32 s_log_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 u32 s_mnt_count; // Mount count u16 s_max_mnt_count; // Maximal mount count u16 s_magic; // Magic signature // more non-essential fields u16 s_inode_size; // size of inode structure };

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

    struct ext2_ group_ desc ( u32 bg_ block_ bi tmap; // Bmap block number u32 bg inode_ bi tmap; //Imap b1ock number u32 bg inode_ table; // Indes 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] ; };

     

  • Block#8:块位图(Bmap)(bg_block_bitmap)位图用来表示某种项的位序列,例如,磁盘块或索引节点。位图用于分配和回收项。在位图中,0位表示对应项处于FREE状态,1位表示对应项处于IN_USE状态。一个软盘有1440块。

  • Block#9:索引节点位图(Imap)(bg_inode_bitmap)一个索引节点就是用来代表一个文件的数据结构。EXT2文件系统是使用有限数量的索引节点创建的。各索引节点的状态用B9中Imap中的一个位表示。在EXT2 FS中,前10个索引节点是预留的。

  • 索引节点Block#10:索引(开始)节点块(bg_inode_table)每个文件都用一个128字节(EXT4中的是256字节)的独特索引节点结构体表示。

 

struct ext2_ inode { u16 i_ mode;// 16 bits - ttttlugsIrwxJrwxIrwxl u16 i_ uid;//owner uid u32 i_ size;//file size in bytes u32 i_ atime;//time fields in seconds u32 i_ ctime;// since 00:00:00,1-1-1970 u32 i_ mtime; u32 i_ dtime; u16 i_ gid;// group ID u16 i_ 1 inks_ count;// hard-link count u32 i_ blocks;// number of 512-byte sectors u32 i_ flags;//IGNORE u32 i_ reserved1 ;//IGNORE u32 i_ b1ock[15] ;//See details below u32 i_ pad[7] ;//for inode size = 128 bytes }

 

  • 直接块:i_block[0]至i_block[11]指向直接磁块盘

  • 间接块:i_block[12]指向一个包含256个块编号的磁盘块,每个块编号指向一个磁盘块

  • 双重间接块:i_block[13]指向一个指向256个块的块,每个块指向256个磁盘块

  • 三重间接块:i_block[14]对于小型EXT2文件可忽略,索引节点大小用于平均分割块大小,所以每个索引节点块都包含整数个索引节点。

  • 目录条目 EXT2目录条目;目录包含dir_entry_2结构,即:

     

    struct ext2_dir_entry_2 { u32 inode; u16 rec_len; u8 name_len; u8 file_type; char name[EXT2_NAME_LEN]; };

    dir_entry是一种可扩充结构。名称字段包含1到255个字符,不含终止NULL。所以dir_entry的rec_len也各不相同。

邮差算法

 

编程示例

 

遍历EXT2文件系统树

遍历算法:

一、读取超级块;

二、读取块组描述符;

三、读取InodeBegin Block,以获取/的索引节点;

四、将路径名标记为组件字符串;

五、从3.中的跟索引节点开始搜索;

六、使用索引节点号ino来定位相应的索引节点七、重复第5第6步。

搜索函数:

u32 search(INODE *inodePtr,char *name){

//search for name in the data blocks of current DIR inode

//if found,return its ino;else return 0

}

利用循环体调用search()n次,搜索循环成功结束,ip必须指向路径名的索引节点。遍历有多个组的大型EXT2/3文件系统也是类似的操作。

将路径名转换为索引节点

已知一个包含EXT2文件系统和路径名的设备,编写C语言函数

INODE *path2inode(int fd,char *pathname)

返回一个指向文件索引节点的INODE指针;文件不可访问返回0.

EXT2文件系统的实现

文件系统结构

 

img

 

三个级别:

第一级别实现基本文件系统树;

第二级别实现文件读/写函数;

第三级别实现系统的挂载,卸载和文件保护

 

基本文件系统

1级文件系统函数

  • mkdir 算法:创建一个带路径名的新目录

mkdir pathname
  • creat 算法:创建一个空的普通文件

Algorithm of creat
  • rmdir 算法:删除目录(前提是目录必须为空)

rmdir dirname
  • link 算法:创建应用于普通文件的硬链接

link old_file new_file
  • unlink 算法:取消文件链接,将文件的links-count减一并从其父目录中删除文件名。当links_count为0时,通过释放它的数据块和索引节点来真正删除文件。

UNlink filename
  • symlink 算法:创建新文件和旧文件的符号链接。符号链接不同于硬链接,它可以链接到任何对象,包括目录,甚至不同设备上的文件。

  • readlink 算法:读取符号文件的目标文件名并返回目标文件名的长度。

2级文件系统函数

实现了文件内容的读/写操作

3级文件系统

支持文件系统的挂载、卸载和文件保护。

 

文件锁定

文件锁定机制允许进程对一个文件或文件的某些部分设置文件锁,以防止在更新文件时出现竞态条件。文件锁可共享(允许同步读取),也可独占(执行独占写)。文件锁既可以是强制性的,也可以是建议性的。例如, Linux既支持共享文件锁,也支持独占文件锁,但文件锁定只是建议性的。在 Linux I中,文件锁可通过ntl(系统调用设置,也可通过fock系统调用操作。为简单起见,我们假设一种非常简单的文件锁定。

当一个进程试图打开一个文件时,将会检查目标操作模式的兼容性。唯一容模式是读模式。如果已经为更新模式打开了一个文件,即写读写追加,则该文件无法再次打开。但是,这并不会阻止相关进程(例如父进程和子进程)修改父进程打开的同一文件,而且在Unix/ Linux中同样如此。在这种情况下,文件系统只能保证每个写操作是原操作,但不能保证进程的写入顺序,写入顺序取决于进程调度。

文件系统项目的扩展

简单的EXT2文件系统使用1KB块大小,只有一个磁盘块组它可以轻松进行以下扩展。

(1)多个组:组描述符的大小为32字节对于1KB大小的块,一个块可能包含

1024/32=32组描述符。32个组的文件系统大小可以扩展为32*8=256MB

(2)4KB大小的块:对于4KB大小的块和一个组,文件系统大小应为4*8=32MB。

对于一个组描述符块,文件系统可能有128个组,可将文件系统大小扩展到128*32=4GB

对于2个组描述符块,文件系统大小为8GB等。大多数扩展都很简单,适合用于编程项目。

(3)管道文件:管道可实现为普通文件,这些文件遵循管道的读/写协议。此方案的优点是:它统一了管道和文件索引节点,并允许可被不相关进程使用的命名管道。为支持快速读/写操作,管道内容应在内存中,比如在 RAMdisk中。必要时,读者可将命名管道实现为FIFO文件。

(4)I/O缓冲:在编程项目中,每个磁盘块都是接读写的。这会产生过多的物理磁盘I/O操作。为提高效率,实际文件系统通常使用一系列I缓冲区作为磁盘块的缓存内存。文件系统的IO缓冲将会在第12章中讨论,但是可把它合并到文件系统.

 

原文地址:https://www.cnblogs.com/Aegon-Targaryen/p/15417254.html