linux的虚拟文件系统VFS
本文將描述Linux內核中的VFS(Virtual File System)。對于VFS這個概念其實非常容易理解,無非是一個抽象的統一接口:它定義了所有文件系統都支持的基本的和概念上的接口和數據結構,這樣就 在用戶上層看來,無論對何種文件系統都擁有統一的接口,和操作方式。其實,對VFS的理解停留在這個層面上對于掌握其思想已經夠用了,剩下要討論的也就是 它的實現和一些和進程和文件系統的外延部分了。
目前總有一些困惑就是對于一個問題或者概念的抽象層次的把握,比如對于一個軟件工程師,他需要對計算機有所了解,不過不可能做到樣樣深入,比如內存,我們 需要知道它是用來存儲臨時數據的,性能介于寄存器和磁盤之間,我們不需要知道它是如何設計的,經過多少工藝制作而成的。所以有的時候,你對一個問題的抽象 層次決定著你對問題的把握。因為不可能完全把問題從最底層剖析,我們只能在我們所熟知的層面或者說是我們所需要的層面去剖析問題。
話題有些扯遠了,不過我想表達的是,如果只是想知道VFS是什么東西的話,第一段的幾句話我認為已經夠用了。那么繼續深入的意義究竟何在呢?或者說目的究竟何在呢?我認為有這么幾點吧:
1. 文件系統的內存表示
文件系統一方面定義了如何在磁盤上組織用戶的數據信息,那如何高效的讀寫管理文件就是內核要考慮的事情了。VFS就是linux用來管理文件系統的方式(當然不僅僅是vfs,還牽涉到I/O等等方面)。
2. VFS設計
VFS是一個比較成功的例子,它為所有的文件系統提供統一的接口,這個思想和設計可以被借鑒到其他地方。另外VFS用到的面向對象的概念,所以這又是一個c語言實現的面向對象范例。
3. 算法
對dcache中用到LRU. slab存儲dentry
?
好了,有了目標,那接下來就是各取所需了。
文件系統的內存表示
這個標題有點起大了,更貼切的應該說是vfs中的一些數據結構。
首先來說一下Linux中用到的和文件系統相關的傳統抽象概念:文件,目錄項,i-node,mount point
這里我想從i-node說起,因為i-node本身的概念使得文件和目錄項并不是我們通常說想象的那樣了。i-node是*nux文件系統中用來表示文件和目錄的數據結構。也就是說通過i-node我們可以知道文件的所有信息。具體的描述可以參考另一篇文章:Ext3 File system Disk Layout
那么如果i-node已經代表文件和目錄,那么這里的文件和目錄項又是什么意思呢?
文件對象
我們先說文件對象,這里的文件對象是指打開的文件在內存中的表示。該對象由open()系統調用創建,由close()系統調用銷毀。也就是說一個文件系 統中的文件可能存在多個對應的文件對象。它其實是用在進程的角度的,多個進程可以同時打開同一個文件,不過打開的文件會有自己特有的狀態信息,比如文件的 偏移量。所有在內存中需要有這個對象記錄這些信息。
這個對象是以struct file **fd;形式存儲的,如下圖所示,一個fd指向一個File Object。
?
當然File Object又應該指向其對應的i-node,雖然事實上File Object并沒有存inode的指針,而是存著dentry的指針(dentry指向i-node)。這里就引出了下一個概念:目錄項(dentry)
目錄項與目錄項緩存
我們既然有了i-node來表示目錄,那為什么還需要dentry呢?原因是VFS經常需要執行目錄相關的操作,比如路徑名查找等。路徑名查找需要不斷的 解析路徑,為了方便起見,就引入了dentry這個概念。目錄項沒有對應的磁盤數據結構,VFS根據字符串形式的路徑名現場創建它。
dentry就是目錄的內存表示,比如/tmp/test這個路徑,內核為根目錄"/”創建一個目錄項對象,為tmp創建一個第二級目錄項對象,為 test創建第三級目錄項對象。這里要說明的是/tmp/test和/home/test中test目錄項有什么不同,雖然名字同是test,不過很顯然 它們指的是不同的文件,所以它們的i-node不同。另外,在dentry中會記錄其父目錄的目錄項對象d_parent。當然,如果/home /test是鏈接到/tmp/test文件上,它們就會有相同的i-node,不過它們的父目錄的目錄項不同,一個是tmp,而另一個是home。可見, 對目錄項的hash就應該是針對當前文件名和父目錄的目錄項對象。
現在我們來說一下目錄項高速緩存:
1. 所有未使用的目錄項對象都存放在一個LRU的雙向鏈表中,既然是LRU,那當目錄項高速緩存空間減少的時候會從LRU的尾部刪除。這個鏈表頭存放在dentry_unsued變量中,鏈表由每個dentry的d_lru變量鏈接。
2. 在使用的目錄項對象是被相應的i-node節點的i_dentry變量所指向,i_dentry同樣是一個list頭指針,這里用list的原因是每個 i-node節點可能與若干硬連接關聯。而目錄項對象的d_alias變量存放這個鏈接表的相鄰元素。當在使用的目錄項對象被刪除時就會被移動到上面所說 的未使用目錄項的LRU中。
3. 散列表dentry_hashtable是一個鏈表的數組,其作用是用來快速定位dentry的,其hash函數是由目錄項的parent指針和文件名決定的。
這里順便提一下,dentry對象是存儲在kernel的slab分配器高速緩存中的,是在Dcahce.c中的dentry_cache。slab高速緩存是內存對象管理的一種算法,這個已經超出了本文的范圍。
Mount Point
//TODO:
?
路徑名查找
//TODO:
以上引用來自http://blog.sina.com.cn/s/blog_55465b4701017qoz.html
?
轉載于:https://www.cnblogs.com/pxguoo/archive/2013/04/07/3003977.html
總結
以上是生活随笔為你收集整理的linux的虚拟文件系统VFS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用EditPlus 删除文本文件中多余
- 下一篇: 股票跳水什么意思