1. 程式人生 > >Linux文件系統之ext2

Linux文件系統之ext2

ron 描述 內核 img mage name 利用 cto OS

  一

  • 首先對於Linux系統來說,如圖所示,系統層級分為用戶層、內核層、以及物理設備層、

                        技術分享圖片

  • 例如C語言中對於文件的寫操作,首先C語言本身會設置緩沖區,來提高讀寫效率。C寫函數會調用linux的系統函數接口write(),這是在用戶態下。緊接著write()會調用linux系統內核函數進入到內核層進行寫入,這個寫操作顯然是由文件系統來控制的,而內核中依舊還有一個高速緩沖設備來提高讀寫效率,之後通過設備驅動寫入磁盤中,簡單來說從調用C讀寫函數到將數據操作到磁盤上是這樣的流程。

  二

  • 當我們了解了Linux文件系統所處的位置之後,接下來說明一些基本概念

  1)扇區:扇區並不是一個物理概念,而是一個單位,大小是521Byte

  2)塊:是一個Linux文件系統的基本單元,大小是4096Byte

  3)塊組:ext2文件系統是以塊組為基本單元

  4)Inode:存儲文件基本信息(除文件名和文件類型),一個文件對應一個Inode;在ext2文件系統中,大小是128Byte

  • 接下來開始解釋ext2文件系統,如圖所示,ext2采用一下的基本結構來管理數據存儲,每一個Block Group為一個基本單元,了解基本單元後就了解了文件系統

                      技術分享圖片

  Boot Block:啟動塊,大小是1KB;存儲磁盤分區信息和啟動信息;PS:一個文件系統只有1份

  Super Block:超級塊,大小是1塊;為了提高系統的健壯性,每一個塊組都有一個(ext4采用稀疏拷貝),並且每份內容一致;用來描述整個分區的文件系統信息;

        例如塊大小、文件系統版本號、上次mount的時間等等

  GDT:塊組描述符表,大小是多個塊,塊數不確定;由很多塊組描述符組成,整個分區分成多少個塊組就對應有多少個塊組描述符。

     每個塊組描述符(Group Descriptor)存儲一個塊組的描述信息,例如在這個塊組中從哪裏開始是inode表,從哪裏開始是數據塊,

     空閑的inode和數據塊還有多少個等等。和超級塊類似,塊組描述符表在每個塊組的開頭也都有一份拷貝,這些信息是非常重要的,

     一旦超級塊意外損壞就會丟失整個分區的數據,一旦塊組描述符意外損壞就會丟失整個塊組的數據,因此它們都有多份拷貝。

     通常內核只用到第0個塊組中的拷貝,當執行e2fsck檢查文件系統一致性時,第0個塊組中的超級塊和塊組描述符表就會拷貝到其它塊組

    ,這樣當第0個塊組的開頭意外損壞時就可以用其它拷貝來恢復,從而減少損失。

  Block Bitmap:塊位圖,原理和Bitmap算法一致(用每位來表示數據);標誌每個塊的使用情況(0沒被使用,1被使用)一個塊組中的塊是這樣利用的:

          數據塊存儲所有文件的數據,比如某個分區的塊大 小是1024字節,某個文件是2049字節,那麽就需要三個數據塊來存,

          即使第三個塊只存了一個字節也需要 占用一個整塊;超級塊、塊組描述符表、塊位圖、inode位圖、inode表這幾部分存儲該塊組的描述信息。 那麽如何知道哪些塊已經用來存儲文件數據或其它描述信息,哪些塊仍然空閑可用呢?

         塊位圖就是用來描述整個塊組中哪些塊已用哪些塊空閑的,它本身占一個塊,其中的每個bit代表本塊組中的一個塊,這個bit為 1表示該塊已用,這 個bit為0表示該塊空閑可用。

  Inode Bitmap:和塊位圖類似,本身占用一個塊;其中每一位表示一個inode是否可用;

  Inode Table:存儲Inode的表,inode表占多少個塊在格式化時就要決定並寫入塊組描述符中,mke2fs格式化工具的默認策略是

  一個塊組有多少個8KB就分配多少個inode。

  Data Blocks:存儲數據

  

  三

  • 接下來說明一下Inode結構

                            技術分享圖片

  如圖所示,一個數據指針指針指向一個數據塊,後三個多級指針為了拓展數據塊

四 文件放入flow

  1. 先找GDT,查看InodeTable所在位置

  2. 查找Table裏未被使用的最小值分配給文件使用,

  3. Inode Bitmap對應位置由0置1

  4. Inode存放文件信息,更新Table

  註:1)文件系統很復雜,以上只是放入文件大致flow,實際系統還有空閑檢測、動態分配等

    2)文件刪除只是將Inode BItma由1置0,更新block bimap 更行GDT,所以文件並沒有真正被刪除

五 目錄結構

  一個目錄占一個塊或多個塊,目錄塊內容如下:

              技術分享圖片

  註:1. 符號連接是新建一個記錄項,指向次文件記錄項

    2. 硬鏈接是新建一個記錄項,指向此文件

  

附:遞歸列出目錄中的文件列表

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <dirent.h>

#include <stdio.h>

#include <string.h>

#define MAX_PATH 1024

/* dirwalk: apply fcn to all files in dir */

void dirwalk(char *dir, void (*fcn)(char *)) {

char name[MAX_PATH];

struct dirent *dp; DIR *dfd;

if ((dfd = opendir(dir)) == NULL) {

fprintf(stderr, "dirwalk: can‘t open %s\n", dir);

return;

}

while ((dp = readdir(dfd)) != NULL) {

if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)

continue; /* skip self and parent */

if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))

fprintf(stderr, "dirwalk: name %s %s too long\n", dir, dp->d_name);

else {

sprintf(name, "%s/%s", dir, dp->d_name);

(*fcn)(name);

}

}

closedir(dfd);

}

/* fsize: print the size and name of file "name" */

void fsize(char *name) {

struct stat stbuf;

if (stat(name, &stbuf) == -1) {

fprintf(stderr, "fsize: can‘t access %s\n", name);

return;

}

if ((stbuf.st_mode & S_IFMT) == S_IFDIR)

dirwalk(name, fsize);

printf("%8ld %s\n", stbuf.st_size, name);

}

int main(int argc, char **argv) {

if (argc == 1) /* default: current directory */

fsize(".");

else

while (--argc > 0)

fsize(*++argv);

return 0;

}

  

  

 

Linux文件系統之ext2