(轉)Minix文件系統框架

摘要:本文介紹了Minix的文件系統框架,包括文件系統的佈局、塊高速緩存、目錄管理和對文件的基本操作。

文件系統佈局

一個Minix文件系統實體包含了i節點、目錄和數據塊。

 

每個文件系統以一個引導塊(bootblock)開始,其中包含可執行代碼,其大小爲1024字節(兩個磁盤扇區)。啓動計算機時硬件首先執行引導塊中的代碼,引導塊則負責操作系統本身的加載。爲防止硬件從非引導設備中啓動,引導塊的固定位置上有一個魔數(magicnumber),啓動設備時硬件會檢查該文件的引導塊中是否存在該魔數。

超級塊(superblock)描述了文件系統的佈局,它給出了文件系統各個部分的大小,其大小爲1024字節。下面給出超級塊的結構定義:

EXTERN structsuper_block {

ino_ts_ninodes;/* 可用的i節點個數*/

zone1_t s_nzones;/* 總的位圖大小,包括位圖等*/

shorts_imap_blocks;/* i節點位圖塊個數*/

shorts_zmap_blocks;/* 區段位圖塊個數*/

zone1_ts_firstdatazone;/*第一個數據塊區段*/

shorts_log_zone_size;/* log2(塊數/區段)*/

shorts_pad;/* 防止關聯編譯的填充位*/

off_ts_max_size;/* 設備上的最大文件長度*/

zone_ts_zones;/*區段個數*/

shorts_magic;/* 魔數*/

 

/* Thefollowing items are valid on disk only for V3 and above */

 

shorts_pad2;/* 防止關聯編譯的填充位*/

unsigned shorts_block_size;/* 塊大小(字節)*/

chars_disk_version;/* 文件系統格式子版本號*/

 

/*下列各項只有超級塊載入內存時才使用*/

struct inode*s_isup;/* 指向被掛載的文件系統根目錄的i節點指針*/

struct inode*s_imount;/* 指向掛載到i節點的指針*/

unsigneds_inodes_per_block;/*魔數的預先計算值*/

dev_ts_dev;/* 超級塊所屬的設備*/

ints_rd_only;/* 該位1表示只讀*/

ints_native;/*該位1表示非字節交換*/

ints_version;/* 文件系統版本號,0意味着魔數異常*/

ints_ndzones;/* 直接區段/i節點*/

ints_nindirs;/* 間接區段/間接塊*/

bit_ts_isearch;/* i節點位圖中的第一個區段位*/

bit_ts_zsearch;/* 區段位圖中的第一個空閒位*/

}

一個磁盤塊如果想用作Minix文件系統,它必須具有圖1所示的結構。工具程序mkfs可經用來創建一個文件系統。

Mkfs/dev/fd1 1440

該命令將在驅動器1的軟盤上創建一個空的1440個塊的文件系統。

Minix系統分別使用i節點位圖和區段位圖來管事i節點和區段。當一個文件被刪除時很容易算出該文件的i節點所在的位圖塊,並利用通常的高速緩存機制查找到該塊。一旦找到它,就把對應於該i節點的那一位清零。區段的釋放過程與此類似。

何謂i節點?i節點(indexnode)是用來實現文件塊到物理塊之間映射而賦給文件的一種數據結構:

EXTERN structinode {

mode_ti_mode;/* 文件類型,保護位等*/

nlink_ti_nlinks;/* 文件的鏈接數*/

uid_ti_uid;/* UID */

gid_ti_gid;/* GID*/

off_ti_size;/* 當前文件長度(字節)*/

time_ti_atime;/* 最後訪問時間(V2only) */

time_ti_mtime;/* 最後修改時間*/

time_ti_ctime;/* i節點最後更改時間(V2only)*/

zone_ti_zone[V2_NR_TZONES]; /* 區段數組*/

 

/* 下列各項不在磁盤上*/

dev_ti_dev;/* 設備標識*/

ino_ti_num;/* i節點號*/

inti_count;/* i節點使用的次數*/

inti_ndzones;/*直接區段(Vx_NR_DZONES)*/

inti_nindirs;/*間接區段/間接塊*/

structsuper_block *i_sp;/*指向超級塊的指針*/

chari_dirt;/* 髒位*/

chari_pipe;/* 管道標識位*/

chari_mount;/* 掛載位*/

chari_seek;/* 位置指針位*/

chari_update;/* ATIME, CTIME,MTIME*/

}

i節點指示了本文件位於磁盤上的哪些存儲塊當中。每個i節點可以指示8個磁盤塊,當實際的文件大小超過8個磁盤塊時就要用到二級間接區段,即一級區段的最後一位不是指向一個實際存儲文件的磁盤塊,而是指向另一個i節點。當使用二級間接塊還不能指示文件的所有存儲位置時可以依次類推使用三級間接塊。

塊高速緩存

MINIX使用塊高速緩存來改進文件系統性能。高速緩存用一個緩衝數組來實現,其中每個緩衝區由包含指針、計數器和標誌的頭以及用於存放磁盤塊的體組成。所有未使用的緩衝區均使用雙鏈表,按最近一次使用時間從近到遠的順序鏈接起來。

 

2.塊高速緩存使用的鏈表

爲了迅速判斷某一塊是否在內存中,我們使用了哈希表。所有緩衝區,如果它所包含塊的哈希代碼爲k,在哈希表中用第k項指向的單鏈錶鏈接在一起。哈希函數提取塊號低n位作爲哈希代碼,因此不同設備的塊可以出現在同一哈希鏈之中。每個緩衝區都在其中某個鏈中。在MINIX啓動,初始化文件系統時,所有緩衝區均未使用,並且全部在哈希表第0項指向的單鏈表中。這時,哈希表其他項均爲空指針。但是一旦系統啓動完成,緩衝區將從0號鏈中刪除,放到其他鏈中。

get_block系統調用負責尋找文件塊。該系統調用需要兩個參數:設備號和塊號。這兩個值與緩衝區鏈中對應域相比較,如果找到包含這一塊的緩衝區,則緩衝區頭中標誌塊使用次數的計數器加1,並返回指向該緩衝區的指針。如果在哈希表中未找到這樣的塊,我們可以使用LRU鏈中的第一個緩衝區。LRU鏈中的緩衝區必然不在使用中,因而它包含的塊可以被換出內存,以釋放這個緩衝區。

目錄管理

Minix中目錄實際上是一種特殊的文件。系統提供了64字節的目錄項,其中4字節用來存放i節點號,60個字節用來存放文件名。

下圖展示了路徑/home/zcy/doc/是如何查找的。

 

 

 

根目錄 i節點776i節點13215


3.尋找路徑/home/zcy/doc/的過程

mount系統調用實現文件系統的掛載。

mount -o loopminix3.iso /mnt/

是把ISO鏡像文件minix3.iso掛載到路徑/mnt/下。掛載前後的文件樹結構如下圖所示。

 

              圖4.掛載前

 

        圖5.掛載後

Minix系統中使用文件鏈接可以讓一個文件同時出現在多個不同的目錄下,link( file_name , link_name)系統調用用於創建鏈接文件。文件的鏈接數是受限制的,不能超過LINK_MAX(在文件include/limits.h中被定義爲SHRT_MAX)。在這種情況情況被鏈接的文件在磁盤上只一個物理複本,所以當一個目錄下的文件被修改時,其他路徑下的鏈接文件也會發生相應更改。i節點中保存着文件的鏈接數,當刪除一個文件時該數目減1,當減到0時徹底從磁盤上刪除文件。

文件操作

對文件的操作包括創建、打開、讀、寫和關閉文件。在/servers/fs/open.c中我們看到了下面幾個函數:do_createdo_opencommon_opennew_nodepipe_opendo_mknodedo_mkdirdo_closedo_lseek

do_createdo_open函數分別用於創建和打開一個文件,創建或打開一個文件一般包括三個步驟:1.找到i節點(如果是一個新文件,需要分配i節點並進行初始化);2.找到或創建相應的目錄項;3.爲文件建立並返回一個文件描述符。何謂文件描述符?文件描述符包含了文件指針和i節點指針,一個文件被打開時就把一個文件描述符返回給打開它的進程。由於一個文件可以被多外進程打開,但是不同進程對文件進行操作的起始位置是不同的,如一個進程可能要從文件開始處讀文件,而另一個進程要從文件結尾處開始向文件中追加寫入新的內容,所以一個進程打開一個文件時它還要獲取對文件操作的起始位置。

common_open完成創建和打開文件的共同操作。它首先檢查是否有空閒的文件描述符及空閒的filp表項。如果是要創建一個新文件,則執行new_node函數。如果目錄已存在,new_node將返回相應的i節點指針;否則它會創建一個新的目錄項和i節點。打開已有文件時文件系統要檢查它的類型和模式(-rwx),以確保它可以被打開。

pipe_open專用來打開一個管道文件。do_mknode函數與do_create類似,它僅僅用來創建i節點併爲其分配一個目錄項。do_mkdir用來創建一個目錄,目錄不可能爲空,因爲在創建它時至少包含了兩個目錄項“.”和“..”,分別指向當前目錄及其父目錄。

關閉文件調用do_close函數,對於普通文件只需把filp計數器減1並看實驗室是否爲0,若爲0則調用put_inode收回i節點。do_lseek用於定位文件中的位置,這在進行文件讀寫時十分有用。

關於讀文件的相關函數在/servers/fs/read.c中。系統把讀文件的請求分解成若干個小塊,每個小塊都在一個單獨的磁盤塊中,它從當前位置開始,直到滿足下列條件之一:

  1. 所有字節都已讀完。

  2. 遇到一個塊邊界。

  3. 讀到文件末尾。

rw_chunk函數的功能是完成對每一個單獨的磁盤塊的讀操作。該函數以i節點和文件位置爲參數,把它們轉換爲一個物理磁盤塊號,然後把請求傳到用戶空間中。相對文件位置與物理地址的映射是在read_map函數中完成的,它能夠處於i節點和間接塊。當讀取一個間接塊時需要調用rd_indir函數。

寫文件的代碼放在write.c中。寫文件與讀文件類似,do_write函數只是在調用rwad_writer時設置WRITEING標誌位。讀和寫的主要區別在於寫文件需要分配新的磁盤塊。

對文件進行操作時需要滿足Minix系統對文件設置的保護規則。每一個文件都有三組rwx位,分別用於文件所有者、所有者所在的組、其他用戶。rwx分別表示可讀可寫可執行,可以通過chmod系統調用來設置文件的保護位。

原文來自:博客園(華夏35度)http://www.cnblogs.com/zhangchaoyang 作者:Orisun
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章