當創建一個文件的時候,作業系統發生了什麼

  • 2020 年 3 月 12 日
  • 筆記

操作文件是我們平時經常有的操作。但是我們可能並不是很了解他們原理,比如為什麼刪除一個很大的文件,會非常快?創建一個文件的時候,系統發生了什麼?為什麼刪除的文件,還可以恢復?知其然知其所以然。我們一起深入探索文件系統的一些原理。這篇先分析一下創建文件的過程。

我們先看一下文件系統在硬碟中的布局。

在這裡插入圖片描述

我們再看一下文件系統在記憶體中的布局。

在這裡插入圖片描述

對著上面的圖,從左向右,我們看到 1 一個進程有一個文件描述符數組,這個描述符數組的元素,就是我們平時操作文件的時候,使用的那個fd。定義如下:

struct file * filp[NR_OPEN];

2 每個文件描述符只是索引,他對應的項指向一個file結構體,file結構體定義如下。

// 管理打開文件的記憶體屬性的結構,比如操作位置(inode沒有讀取操作位置這個概念,),實現系統進程共享inode  struct file {      unsigned short f_mode;      unsigned short f_flags;      unsigned short f_count;      struct m_inode * f_inode;      off_t f_pos;  };

file結構體是和inode的作用是不一樣的,inode是更多的是存儲文件的一些持久化的數據,比如大小,時間、屬主,數據塊位置等。inode是存在硬碟中的。在操作的文件的時候才會載入到記憶體。如果有修改,需要回寫硬碟。file存儲的是文件臨時的元數據,他只存在記憶體里。比如一個文件當前讀寫位置,打開模式等等。關閉文件後就會丟失這些數據。

3 在文件系統中,每一個文件都對應一個inode結構體。inode保存了一個文件的元數據,包括大小,時間,屬主,塊號等等。inode存在於硬碟和記憶體,記憶體的inode叫m_inode,他的部分屬性和硬碟inode一一對應(硬碟inode叫d_inode),還有一些是只存在記憶體中的屬性。我們看一下inode在硬碟中的布局。

在這裡插入圖片描述

了解一系列結構體後,我們開始分析創建文件的這個過程。主要是兩件事情,第一,判斷文件是否存在,如果不存在則開始創建。

1 根據路徑找到最後一級目錄對應的inode節點。目錄其實也是文件,他和一般文件的區別是,一般文件存儲的是用戶數據,目錄文件存儲的是文件資訊。目錄文件里存儲的數據就是一個對象數組,每個元素保存了文件名和inode節點號。

// 目錄項結構  struct dir_entry {      // inode號      unsigned short inode;      // 文件名      char name[NAME_LEN];  };

假設我們找/a/b/hello.txt這個文件。因為/是根文件系統的根路徑,他在文件系統初始化的時候,根文件系統會從固定的位置(第一個inode節點),把他對應的inode結構體載入到記憶體中。我們根據根inode,就知道根目錄下面有多少dir_entry,然後逐個比較找到目錄a對應的dir_entry,從dir_entry中得到目錄a的inode號,再根據a的inode號把inode結構體從硬碟中載入到記憶體,繼續這個過程,直到最後找到hello.txt。

2 所以我們從一個目錄下找一個目錄或者文件的時候,其實就是遍歷這個數組,對比name是否一樣,是的話根據inode號取出inode結構體,從而取得文件數據。

3 因為我們是創建文件,所以是肯定找不到的。

4 上面已經解釋過,一個文件對應一個inode。現在我們創建一個文件,那自然,我們就要先在硬碟中申請一個inode,並且修改文件系統的元數據inode點陣圖,即這個inode被使用了。然後再在記憶體中申請一個m_inode。供用戶操作文件的。至此,創建文件就完成了。我們發現,創建一個文件,底層發生的事情其實就是在硬碟申請一個inode就可以了。

5 當我們開始操作m_inode對應的文件的時候。比如寫入。回歸上面的inode結構體可以發現,這時候文件其實是沒有被分配硬碟空間的。現在需要寫入,那首先就要先在硬碟中申請一塊空間。並修改塊點陣圖資訊。然後申請一塊和該硬碟塊關聯的記憶體塊,用戶寫入的數據就存在該記憶體塊中,系統會定時回寫到硬碟中對應的塊。

這就是創建一個文件的大致過程。