1. 程式人生 > >VFS檔案系統結構分析

VFS檔案系統結構分析

本文乃fireaxe原創,使用GPL釋出,可以自由拷貝,轉載。但轉載請保持文件的完整性,並註明原作者及原連結。內容可任意使用,但對因使用該內容引起的後果不做任何保證。

作者:[email protected] 部落格:fireaxe.blog.chinaunix.net
VFSLinux非常核心的一個概念,linux下的大部分操作都要用到VFS的相關功能。這裡從使用者的角度,對VFS進行了簡單說明。使用者不但需要知道Linux下有哪些檔案操作的函式,還需要對VFS的結構有一個比較清晰的瞭解,才能更好的使用它。例如hard link symbolic,如果沒有VFS結構的相瞭解,就無法搞清楚如何使用它們。
本文首先是建立了一個簡單的目錄模型,然後介紹該目錄在
VFS的結構,最終總結出如何使用各個檔案操作函式。

本著簡單使用的原則,主要使用了分析加猜測的方法。鑑於本人水平有限,文中不免會有些錯誤。歡迎各位讀者理性閱讀,大膽批判。您的批判是我進步的動力。

1    目錄模型

以下面的目錄為例。

dir為第一級目錄,dir中有subdir0與subdir1兩個子目錄與一個檔案file0。“subdir0”中有兩個檔案file1與file0。subdir1中有一個檔案file3。

2     VFS的概念

VFS是Linux中的一個虛擬檔案檔案系統,也稱為虛擬檔案系統交換層(Virtual Filesystem Switch)。它為應用程式設計師提供一層抽象,遮蔽底層各種檔案系統的差異。如下圖所示:

不同的檔案系統,如Ext2/3、XFS、FAT32等,具有不同的結構,假如使用者呼叫open等檔案IO函式去開啟檔案,具體的實現會非常不同。為了遮蔽這種差異,Linux引入了VFS的概念。相當於是Linux自建了一個新的貯存在記憶體中的檔案系統。所有其他檔案系統都需要先轉換成VFS的結構才能為使用者所呼叫。

3     VFS的構建

所謂VFS的構建就是載入實際檔案系統的過程,也就是mount被呼叫的過程。如下圖所示,以mount一個ext2的檔案系統為例。

這是一個經過簡化的Ext2磁碟結構,只是用於說明用它構建VFS的基本過程。

mount命令的一般形式為:mount /dev/sdb1 /mnt/mysdb1

/dev/sdb1是裝置名,/mnt/mysdb1是掛載點。

VFS檔案系統的基本結構是dentry結構體與inode結構體。

Dentry代表一個檔案目錄中的一個點,可以是目錄也可以是檔案。

Inode代表一個在磁碟上的檔案,它與磁碟檔案一一對應。

Inode與dentry不一定一一對應,一個inode可能會對應多個dentry項。(hard link)

Mount時,linux首先找到磁碟分割槽的super block,然後通過解析磁碟的inode table與file data,構建出自己的dentry列表與indoe列表。

需要注意的是,VFS實際上是按照Ext的方式進行構建的,所以兩者非常相似(畢竟Ext是Linux的原生檔案系統)。

比如inode節點,Ext與VFS中都把檔案管理結構稱為inode,但實際上它們是不一樣的。Ext的inode節點在磁碟上;VFS的inode節點在記憶體裡。Ext-inode中的一些成員變數其實是沒有用的,如引用計數等。保留它們的目的是為了與vfs-node保持一致。這樣在用ext-inode節點構造vfs-inode節點時,就不需要一個一個賦值,只需一次記憶體拷貝即可。

如果是非EXT格式的磁碟,就沒有這麼幸運了,所以mount非EXT磁碟會慢一些。

4     VFS的結構

構建出VFS檔案系統後,下一步是把第一節中提到的目錄模型對映到VFS結構體系中。

上文提到了VFS主要由denty與inode構成。Dentry用於維護VFS的目錄結構,每個dentry項就代表著我們用ls時看的的一項(每個目錄和每個檔案都對應著一個dentry項)。Inode為檔案節點,它與檔案一一對應。Linux中,目錄也是一種檔案,所以dentry也會對應一個inode節點。

下圖是第一節中的目錄模型在VFS中的結構。

5     Dentry cache

每個檔案都要對應一個inode節點與至少一個dentry項。假設我們有一個100G的硬碟,上面寫滿了空檔案,那個需要多少記憶體才能重建VFS呢?

檔案最少要佔用1個block(一般是4K)。假一個dentry與一個inode需要100byte,則dentry與inode需要佔用1/40的空間。100G硬碟則需要2.5G空間。最近都開始換裝1T硬碟了,需要 25G的記憶體才能放下inode與dentry,相信沒有幾臺電腦可以承受。

為了避免資源浪費,VFS採用了dentry cache的設計。

當有使用者用ls命令檢視某一個目錄或用open命令開啟一個檔案時,VFS會為這裡用的每個目錄項與檔案建立dentry項與inode,即“按需建立”。然後維護一個LRU(Least Recently Used)列表,當Linux認為VFS佔用太多資源時,VFS會釋放掉長時間沒有被使用的dentry項與inode項。

需要注意的是:這裡的建立於釋放是從記憶體佔用的角度看。從Linux角度看,dentry與inode是VFS中固有的東西。所不同的只是VFS是否把dentry與inode讀到了記憶體中。對於Ext2/3檔案系統,構建dentry與inode的過程非常簡單,但對於其他檔案系統,則會慢得多。

瞭解了Dentry cache的概念,才能明白為何下面會有兩種定位檔案的方式。

6     無dentry時定位檔案

因為上面提到的Dentry Cache,VFS並不能保證隨時都有dentry項與inode項可用。下面是無dentry項與inode項時的定位方式。

為了簡化問題,這裡假設已經找到了dir的dentry項(找到dentry的過程會在後面講解)。

首先,通過dir對應的dentry0找到inode0節點,有了inode節點就可以讀取目錄中的資訊。其中包含了該目錄包含的下一級目錄與檔案檔案列表,包括name與inode號。實際上用ls命令檢視的就是這些資訊。“ls -i”會顯示出檔案的inode號。

>  ls -i

975248 subdir0  975247 subdir1   975251 file0

然後,根據通過根據subdir0對應的inode號重建inode2,並通過檔案資料(目錄也是檔案)與inode2重建subdir0的dentry節點:dentry1。

>  ls -i

975311 file1 975312 file2

接著,根據file1對應的inode號重建inode4,並通過檔案資料與inode4重建file1的dentry節點。

最後,就可以通過inode4節點訪問檔案了。

注意:檔案對應的inode號是確定的,只是inode結構體需要重新構造。

7     有dentry時定位檔案

一旦在Dentry cache中建立了dentry項,下次訪問就很方便了。

Dentry中的一個關鍵變數是d_subdirs,它儲存了下一級目錄的列表,用於快速定位檔案。

首先,在代表dir目錄的dentry0的d_subdirs中查詢名字為“subdir0”的dentry項,找到了dentry1。

然後在dentry1中查詢名字為“file1”的dentry項,然後找到了file1對應的dentry項,

最後通過file1對應的dentry項獲得file1對應的inode4。

與無dentry項時比較,有dentry項時的操作精簡了許多。

8     Symbolic link

建立symboliclink的命令為 :ln -s 原始檔 目標檔案

Linux中的symbolic link類似於Windows系統中的快捷方式。如下圖所示,symlink1是指向file1的symbolic link。symlink1本身也是檔案,因此有自己獨立的inode節點。symlink中實際儲存的是原始檔的相對路徑。

大部分檔案操作會直接對symbolic link指向的目標進行操作,比如open(“symlikn1”),實際上開啟的是file3。

如果file3不在會發生什麼事情呢?open函式照樣會按照symlink1中的檔案路徑開啟檔案。但file3不存在,因此會報錯說檔案不存在。


9     hard link

Linux除了symbolic link,還有hard link的概念。

Hard link建立實際上是dentry項的一個拷貝,它們都指向同一個inode節點。當我們使用write改寫file1的內容時,hardlink1的內容也會被改寫,因為所以實際上它們是同一個檔案。

如下圖所示,hardlink1是file1的一個hard link。它們都指向同一個inode1節點。Inode1中有一個計數器,用於記錄有幾個dentry項指向它。刪除任意一個dentry項都不會導致inode1的刪除。只有所有指向inode1的dentry都被刪除了,inode1才會被刪除。

他們實際

從某種意義上講,所有dentry項都是hard link。

10  程序對檔案的管理

程序控制塊task_struct中有兩個變數與檔案有關:fs與files。

files中儲存著root與pwd兩個指向dentry項的指標。使用者定路徑時,絕對路徑會通過root進行定位;相對路徑會的通過pwd進行定位。(一個程序的root不一定是檔案系統的根目錄。比如ftp程序的根目錄不是檔案系統的根目錄,這樣才能保證使用者只能訪問ftp目錄下的內容)

fs是一個file object列表,其中每一個節點對應著一個被打開了的檔案。當程序定位到檔案時,會構造一個file object,並通過f_inode 關聯到inode節點。檔案關閉時(close),程序會釋放對應對應file object。File object中的f_mode是開啟時選擇的許可權,f_pos為讀寫位置。當開啟同一個檔案多次時,每次都會構造一個新的file object。每個file object中有獨立的f_mode與f_pos。



11    open的過程

開啟檔案涉及到裡一系列的結構調整,這裡分步驟進行說明:

首先建立一個檔案管理結構,如下圖所示,該程序已經打開了兩個檔案,接下來我們再開啟一個新檔案。


第一步:找到檔案;

從上文中能定位到我們檔案的inode節點,找到了inode節點也就找到了檔案。

第二步:建立file object;

建立一個新的file object物件,放入file object物件列表,並把它指向inode節點。

第三步:建立file descriptor

file descriptor就是程序控制塊task_struct中files中維護的fd_array。因為是陣列,所以file descriptor實際上已經預先分配好空間了,這裡這是需要把某個空閒的file descriptor與file object關聯起來。這個file descriptor在陣列中的索引號就是open檔案時得到的檔案fd。

12     open與dup

同一個檔案是可以open多次的,結構如下圖所示。每次open都會建立一個新的file descriptor與file object。然後指向同一個檔案的inode節點。下圖中,假設open的檔案與fd1指向的是同一個檔案,則新建立的file object 2與fd1的file  object 2會指向同一個inode2節點。

Linux還提供了dup功能,用於複製file descriptor。使用dup不會建立新的非file object,所以新建立的file descriptor會與原filedescriptor同時指向同一個file object。下圖中,我們通過dup(fd1)得到了fd2,則fd2與fd1指向了同一個file object2。

兩次open後由於會生成新的object,所以檔案讀寫屬性、檔案讀寫位置(f_pos)等資訊都是獨立的。使用dup複製file descriptor後,由於沒有獨立的object,所以修改某個fd的屬性或檔案讀寫位置後,另一個fd也會隨之變化。

13     Fork對開啟檔案的影響

Dup的操作與fork一個子程序時的操作類似。

下圖是已有父程序的檔案結構:


使用fork後的結構如下。同樣是沒有建立新的file object,因此當對parent process中的fd1進行檔案指標的移動時(如讀寫),child process中的fd1也會受影響。也即是說opened files list不是程序的一部分,因此不會被複制。Opened files list應該是一個全域性性的資源連結串列,程序維護的是一個指標列表fd table,所以被複制的只是指標列表fd table,而不是opened files list。


14  檔案操作函式解析

通過上面的分析,可以對各個函式的作用域與使用方式有更清晰的瞭解。下面列出了常用的檔案操作:

函式名

作用物件

說明

creat

dentry, inode

建立檔案時會建立新的dentry與inode

open

file object

如果檔案不存在,且有O_CREAT引數,則會先呼叫creat

close

file object

刪除file object,但不會刪除檔案。

state/lstate

inode

讀取inode的內容。如果目標是symbolic link,stat會讀取symbolic link指向的內容;lstat則會讀取symbolic link檔案本身。

chmod

file object

改變file object中的f_mode

chown/lchown

file object

改變file object中的f_uid與f_gid

truncate

inode

改變檔案長度。

read

file object

讀檔案會改變file object中的f_pos

write

file object,inode

寫檔案改變file object中的f_pos的同時也會改變檔案內容與更新修改時間。

dup

file object

建立一個新的file object

seek/lseek

file object

改變file object中的f_pos

link

dentry

建立新的dentry項,指向同一個inode節點。

unlink

dentry

刪除一個dentry項。如果該dentry指向的inode節點沒有被其他dentry項使用,則刪除inode節點與磁碟檔案。

rename

dentry

修改dentry相中的d_name

readlink

-----------

read無法讀取symbolic link 檔案的內容,需要使用readlink讀取

symlink

dentry, inode

作用與creat類似,但建立的檔案屬性為symbolic link。

注:磁碟檔案與inode節點一一對應,所以在表中不再單獨列出磁碟檔案。


參考檔案:
Advanced Programming in the UNIX Environment (3rd) W. Richard Stevens & Stephen A. Rago
Understanding the Linux Kernel (3rd) Daniel P. Bovet & Marco Cesati

相關推薦

VFS檔案系統結構分析(容易理解)

VFS是Linux非常核心的一個概念,linux下的大部分操作都要用到VFS的相關功能。這裡從使用者的角度,對VFS進行了簡單說明。使用者不但需要知道Linux下有哪些檔案操作的函式,還需要對VFS的結構有一個比較清晰的瞭解,才能更好的使用它。例如hard link 與

VFS檔案系統結構分析

本文乃fireaxe原創,使用GPL釋出,可以自由拷貝,轉載。但轉載請保持文件的完整性,並註明原作者及原連結。內容可任意使用,但對因使用該內容引起的後果不做任何保證。 作者:[email protected] 部落格:fireaxe.blog.chinaunix

Linux VFS 檔案系統結構分析

VFS是Linux非常核心的一個概念,linux下的大部分操作都要用到VFS的相關功能。這裡從使用者的角度,對VFS進行了簡單說明。使用者不但需要知道Linux下有哪些檔案操作的函式,還需要對VFS的結構有一個比較清晰的瞭解,才能更好的使用它。例如hard link 與sy

ext2檔案系統結構分析

轉載自:https://blog.csdn.net/yuzhihui_no1/article/details/50256713 ext2檔案系統 總體儲存佈局 我們知道,一個磁碟可以劃分成多個分割槽,每個分割槽必須先用格式化工具(例如某種mkfs命令)格式化成某種格式的檔案系統,然後才能

FAT32檔案系統結構分析

        FAT,英文為File Allocation Table,文件分配表。先要記住幾個概念:         扇區:一般扇區為512個位元組。         簇:

VFS文件系統結構分析 與socket

pwd windows系統 原則 dev 按需創建 object 路徑 部分 文件內容 本文乃fireaxe原創,使用GPL發布,可以自由拷貝,轉載。但轉載請保持文檔的完整性,並註明原作者及原鏈接。內容可任意使用,但對因使用該內容引起的後果不做任何保證。 作者:fireax

FAT16檔案系統結構扇區資料分析

FAT,英文為File Allocation Table,文件分配表。先要記住幾個概念: 扇區:一般扇區為512個位元組。 簇:由若干個扇區組成,是存取資料的最小單位。如果簇大小為16K,檔案大小為1位元組,那也要用一個簇來存,而且該簇不用再拿來他用。 FAT檔案系統就是專門管理這些簇的

常見檔案系統對比分析(NFS、GFS、NAS)

本章我們來分析下常見檔案系統對比分析,這裡我們主要講解NFS、GFS、NAS相關概念及區別。 《一》NFS NFS 是Network File System的縮寫,中文解釋是網路檔案系統,它是FreeBSD支援的檔案系統中的一種,它允許網路中的計算機之間通過TCP/IP網路共享資源。在N

Ext4檔案系統架構分析(一)

本文描述Ext4 檔案系統磁碟佈局和元資料的一些分析,同樣適用於ext2,ext3檔案系統,除了它們不支援的ext4的特性。整個分析分兩篇博文,分別概述佈局和詳細介紹各個佈局的資料結構及組織定址方式等。 1.Ext4 檔案系統佈局綜述 一個Ext4 檔案系統被分成一系列

linux 檔案系統結構

1 - Linux 和windws 不同,他是沒有碟符的概念的,只有一個根目錄,它是目錄與檔案的源頭,然後從根目錄下一層一層的都是各種檔案。,如同樹枝狀,因此被稱為目錄樹解構。Linux是一切皆檔案。 2 - Linux 是用正斜槓來 " / " 來標識目錄的。 3 - 目錄樹的特點是什麼?   3.1

linux檔案系統結構樹(強烈建議儲存)

根目錄是整個系統最重要的一個目錄,因為不但所有的目錄都是由根目錄衍生出來的, 同時根目錄也與開機/還原/系統修復等動作有關。 由於系統開機時需要特定的開機軟體、核心檔案、開機所需程式、 函式庫等等檔案資料,若系統出現錯誤時,根目錄也必須要包含有能夠修復檔案系

unix/linux 檔案系統結構淺析

一、物理磁碟到檔案系統 檔案系統用來儲存檔案內容、檔案屬性、和目錄。這些型別的資料如何儲存在磁碟塊上的呢?unix/linux使用了一個簡單的方法。如圖所示. 它將磁碟塊分為三個部分: 1)超級塊,檔案系統中第一個塊被稱為超級塊。這個塊存放檔案系統本身的結構資訊。比如

hadoop檔案系統架構分析

(軟體體系結構的大作業,閱讀分析hadoop檔案系統) 寫在前面/後面 FileSystem = abstractFileSystem -》 面向檔案系統實現者 ​ FileContext -》面向應用程式編寫者 FS中具體的檔

為什麼需要makefile檔案和makefile檔案結構分析

本文是學習的總結,適用於初學者,有錯誤懇請指出 在Linux中,所有的原始碼都需要編譯成可執行檔案才能最終執行,實現需要的功能。 寫軟體的時候,如果將所有的功能和程式碼都寫在一個檔案當中,則只需要對這個檔案gcc即可生成想要的可執行檔案。 但規模很大的軟體顯然無法全部寫入一個檔案,另外,

一個簡單PDF檔案結構分析

一個簡單的PDF檔案結構的分析 Adobe的PDF參考告訴我們一個PDF檔案可以通過下面4個方面來理解: 1.         物件, 一個PDF文件是由一組基本資料型別組成的資料結構。 2.         檔案(物理結構), 決定物件是如何存放在一個PDF檔案中的

Linux核心檔案系統掛載分析

http://edsionte.com/techblog/archives/4389?f=http://blogread.cn/ 1.資料結構 下面將對檔案系統掛載過程中涉及到的兩個主要資料結構vfsmount和path進行節本說明。 1.1 struct vfsmo

Linux ext4檔案系統原理-檔案系統結構檔案解析

基本概念 1扇區(sector)=512位元組(byte) 1資料塊(block)=8扇區=4KB(mkfs時指定,預設4KB,可設定為1KB - 64KB) Ext4欄位使用little-endian順序寫入磁碟;但journal日誌使用big-endian順序寫入磁碟。

yaffs2檔案系統結構及應用

        檔案系統是包括在一個磁碟(包括光碟、軟盤、閃盤及其它儲存裝置)或分割槽中的目錄結構;一個可應用的磁碟裝置可以包含一個或多個檔案系統;如果您想進入一個檔案系統,首先您要做的是掛載(mount)檔案系統;為了掛載(mount)檔案系統,您必須指定一個掛載點(所掛

Linux-(1)Linux樹狀檔案系統結構及各資料夾的作用

  Linux檔案系統為一個倒轉的單根樹狀結構.   檔案系統的根為"/"   Linux中所有的東西都是檔案.   如下圖所示:     各資料夾的作用如下:   bin: 存放所有使用者都可以執行的可執行檔案.   boot: 存放系統引導,啟動相關的內容. 其中的

NTFS檔案系統結構--從零開始追蹤一個檔案的位置

前言:最近由於專案需要,研究了一下NTFS檔案系統,NTFS檔案系統是windows使用的檔案系統,包括NT,2000,xp系列。無奈萬惡資本主義的windows將自家的東西全部藏在陰暗的角落,NTFS理所當然地也不開源,儘管沒有原始碼,還是有足夠豐富的資料將NTFS檔案系