0.11版linux文件系統(二)

超級塊描述了整個文件系統的信息,而文件作爲存儲的對象,它的信息是有inode節點來描述的。i節點位圖描述了inode的使用情況。
struct m_inode{
        unsigned short i_mode; //文件類型
        unsigned short i_uid;//文件宿主
        unsigned long i_size;//文件大小
        unsigned long i_mtime;//文件修改時間
        unsigned char i_guid; //文件組id
        unsigned char i_nlinks;        //文件目錄項連接數
        unsigned char i_zone[9];//文件所在的設備邏輯塊號
//以下的字段在內存中
        struct task_struct *i_wait; //等待該i節點的進程
        unsigned long i_atime,i_ctime;
        unsigned short i_dev; //文件所在的設備號
        unsigned short i_num; //i節點號
        unsigned short i_count;//i節點被使用的次數,0表示空閒
        unsigned char i_lock;
        unsigned char i_dirt;
        unsigned char i_pipe;
        unsigned char i_mount; //該節點是否是某個文件系統的安裝節點
        unsigned char i_seek;
        unsigned char i_update;
}
其 中i_zone[9]很重要,它指出了文件使用的設備的邏輯塊號。其中0-6爲直接塊,也就是文件的數據直接在相應的邏輯塊上;7位1級塊,1級塊可以包 含512個邏輯塊號;8位2級塊,它可以存放512個1級塊。所以文件長度在7k以內只使用前7個位指定邏輯塊,再大就要使用間接塊指定了。
對i節點位圖以及i節點的操作有new_inode,free_inode,iget,iput,bmp,以及namei.輔助的函數有get_empty_inode,read_inode,write_inode.內核維護了一個inode節點數組:
struct m_inode inode_table[NR_INODE]={{0,},};
new_inode(int dev)從inode_table中獲取一個空閒的inode節點項,然後相應設備超級塊中的i節點位圖中的第一個0bit,接着設置inode節點信 息,並置引用爲1。free_inode則相反,進行一系列測試後,它清除位圖的相應比特爲,並清空inode節點佔用的內存。
對 邏輯塊位圖的操作有new_block和free_block,前者獲取一個空閒緩衝塊並置位相應比特位,後者相反。以上都是對內存中的inode數組以 及緩衝區中的位圖進行操作,而最終要落實到設備特定的塊上。read_inode是從設備上讀取指定i節點的信息到內存中,write_inode是寫入 指定i節點到設備。後者是將inode寫到相應緩衝塊中,並置位
b_dirt。這裏涉及到計算指定的inode節點在設備上的邏輯塊號:
//啓動塊+超級塊+i節點位圖塊數+邏輯塊位圖塊數+(i節點號-1)/每塊含有的i節點
block=1+1+sb->s_imap_blocks+sb->s_zmap_blocks+(inode->s_inum)/INODES_PER_BLOCK;
iget 函數是從設備上讀取指定的i節點。如同getblk,考慮到同步問題也是個反覆的過程。它首先從i節點表中申請一個空閒i節點。然後搜索i節點表,看是否 有指定的i節點,如果沒有就用read_inode從設備中讀取到空閒節點就可返回。如果有則等待它解鎖。等待過程中如果節點表發生變化那麼要重新搜索。 若該i節點是某個文件系統的安裝點,則讀取相應文件系統的超級塊並設置節點號爲該文件系統的第一個inode,然後重新開始。
iput是回寫到設 備,這裏根據文件的類型有幾種不同的處理方法。如果文件是管道文件,則喚醒管道上等待的進程,並釋放管道頁面。管道的物理內存地址在inode-> i_size字段。如果文件是塊設備,那麼刷新設備。inode->i_zone[0]中存放的是設備號。如果鏈接數爲0,則釋放i節點所有的邏輯 塊,並釋放該節點。
還有一個比較重要的函數是 _bmp,它是將文件數據塊映射到盤塊。在前面講過的do_no_page中用到過,計算出缺頁的內存地址在程序所佔的塊號後,通過bmp映射到設備上的塊號,並讀取被交換到塊設備上的頁面。
下面具體講解一下:
//inode:文件的節點,block:文件中的塊號;create:創建標誌。
static int _bmp(struct m_inode *inode,int block,int create)
{
        struct buffer_head *bh;
        int i;
        if(block<0)
                panic("_bmp:block<0");
//如果塊號大於直接塊數+間接塊數+二次間接塊數,則超出文件系統表示範圍,死機
        if(block>=7+512+512*512)
                panic("_bmp:block>big");
//如果塊號小於7,則使用直接塊表示
        if(block<7){
                if(create&&!inode->i_zone[block])
                        if(inode->i_zone[block]=new_block(inode->i_dev)){
                                inode->i_ctime=CURRENT_TIME;
                                inode->i_dirt=1;
                        }
                return inode->i_zone[block];
        }
//否則就看是不是在間接塊中
        block-=7;
        if(block<512){
//如果間接塊沒有創建且創建標誌爲1,那麼創建間接塊
                if(create&&!inode->i_zone[7])
                        if(inode->i_zone[7]=new_block(inode->i_dev)){
                                inode->i_dirt=1;
                               
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章