Linux系統程式設計【4】——檔案系統
阿新 • • 發佈:2021-02-27
## pwd命令的作用
Linux的檔案系統比較龐大,所以筆者從pwd這一命令入手,在實現的過程中加深對檔案系統的瞭解。
輸入:`man pwd`
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210226132413615.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
從指導文件中可以看到,pwd命令的作用是顯示出當前所處位置,以路徑的形式打印出來。
舉例如下:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210226132724241.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
筆者首先輸入pwd命令,顯示出`/home/lularible`,說明我當前就處在該位置。
當筆者進入其中的一個子目錄"bin"時,再次輸入pwd命令,顯示出`/home/lularible/bin`,這是顯而易見的。
## Linux檔案系統內部結構
為了能夠實現pwd命令,就需要先了解Linux檔案系統的內部結構
### 檔案系統的多層抽象
一般而言,檔案是儲存在硬碟上的,那麼將磁碟這一物理實體,進行邏輯劃分和組織,就是進行抽象的過程。目的就是為了便於管理。
最樸素的管理手段就是,給硬碟的區域編號,按照編號從低到高給檔案分配儲存空間。當然,訪問效率就可想而知了(當檔案數量一多,訪問效率將會及其低下)。所以那些系統開發人員就發揮出自己的聰明才智,對檔案系統進行了巧妙的設計。
#### 第一層抽象:從磁碟到分割槽
一整塊磁碟,能儲存大量的資料,統一管理起來不太方便。若能將它分而治之,則更加靈活。比如說window系統裡面的磁碟分割槽:C盤,D盤,E盤等等。每個分割槽都可以看作是一個獨立的磁碟。
#### 第二層抽象:從磁碟到塊序列
一個磁碟由一些磁性碟片組成。每個碟片的表面都被劃分為很多同心圓,這些同心圓稱作磁軌,每一個磁軌又進一步被劃分為扇區,每個扇區可以儲存一定位元組的資料(如512位元組)。扇區是磁碟上的基本儲存單元,每次空間分配或者訪問都是以一個扇區為最小單位。
#### 第三層抽象:從塊序列到三個區域的劃分
為了儲存不同型別的資料(檔案內容、檔案屬性、目錄),將磁碟塊分為3個部分:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210226135428885.PNG)
- 1.超級塊:檔案系統中的第一個塊被稱為超級塊,用來存放檔案系統本身的結構資訊。
- 2.i-節點表:檔案系統的下一個部分被稱為i-節點表。每個檔案都有一些屬性,如大小、檔案所有者和最近修改時間等。這些性質被記錄在一個稱為i-節點的結構中。所有的i-節點都有相同的大小,並且i-節點表是這些結構的一個列表。
- 3.資料區:檔案系統的第三部分是資料區。檔案的內容儲存在這個區域。
### 建立一個檔案的過程
檔案有內容和屬性,核心將檔案內容存放在資料區,檔案屬性存放在i-節點,檔名存放在目錄。下圖所示為建立一個檔案的例子:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210226224034853.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
其中的幾個主要操作為:
- 1.儲存屬性:核心找到一個空的i-節點(圖中為47),把檔案資訊記錄到該i-節點中。
- 2.儲存資料:核心從空閒磁碟塊表中獲得627、200、992這三個磁碟塊,將核心緩衝區中的資料複製到這三個磁碟塊中。
- 3.記錄分配情況:檔案內容按序存放在磁碟塊627/200/992中。核心在i-節點的磁碟分佈區記錄了上述序列塊。磁碟分佈區是一個磁碟塊序號的列表,這三個編號放在最開始的三個位置。
- 4.新增檔名到目錄:新檔案的名字是userlist。核心將入口(47,userlist)新增到目錄檔案。檔名和i-節點號之間的對應關係將檔名和檔案的內容及屬性連線了起來。
### 目錄的結構
目錄被抽象為一個包含i-節點號和檔名的表。
輸入`ls -ia`可以檢視當前目錄包含的檔案以及對應的i-節點號:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210226230010302.PNG)
如代表當前目錄的"."的i-節點號為1048600,代表上一級目錄的".."的i-節點號為936372。再看一下根目錄的組成:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210227081200963.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
其中"."和".."的i-節點號都是2,說明根目錄的上級目錄就是自己。另外,還可以看到存在i-節點號一樣的檔案(目錄),這就是硬連結,將在後續的軟、硬連結區別一節中敘述。
### 檔案讀取的工作原理
既然知道了目錄的結構,那麼就可以理一遍檔案讀取的過程了。舉例來說:
輸入`cat userlist`,表示讀取userlist這個檔案並顯示。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210227082124969.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
step1.在目錄中尋找檔名
檔名儲存在目錄檔案中,核心在目錄檔案中尋找包含字串"userlist"的記錄。userlist所在的記錄包含編號為47的i-節點。
step2.定位i-節點並讀取內容
核心在檔案系統中的i-節點區域找到i-節點47。i-節點包含資料塊編號的列表。
step3.訪問儲存檔案內容的資料塊
在step2之後,即知道了資料塊的位置和在磁碟中的順序,就可以通過不停的呼叫read函式,使核心不斷將位元組從磁碟複製到核心緩衝區。
ps:讀取許可權的控制:核心根據檔名找到i-節點號,再根據i-節點號找到i-節點。在i-節點中,找到檔案的許可權位和使用者ID,從而判斷該使用者是否具有讀取許可權。
### 大檔案的i-節點
每個檔案對應一個i-節點,而每個i-節點大小是固定的,所以當檔案內容需要佔用很多磁碟塊時,i-節點中的磁碟分佈區可能不夠用。這個時候,就需要採用多級分配的方式。一圖說明問題:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210227085231897.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x1bGFyaWJsZQ==,size_16,color_FFFFFF,t_70)
其中,級數越多,訪問磁碟時就越慢。因為需要按照每一級的指引,多次讀取磁碟。
## 實現pwd
### 思路
- 1.獲得當前目錄的i-節點號,記為stat
- 2.改變目錄至上級目錄
- 3.找到i-節點號stat的名字
重複上述步驟,直到樹頂。到樹頂的判斷依據:一個目錄的"."和".."的i-節點號相同。
### 原始碼
```c