「一切皆是檔案」是 unix/linux 的基本哲學之一。不僅普通的檔案,目錄、字元裝置、塊裝置、套接字等在 unix/linux 中都是以檔案被對待;它們雖然型別不同,但是對其提供的卻是同一套操作介面。另外所謂的塊裝置:是指支援隨機訪問的儲存裝置;與此相對應的是字元裝置,它只支援順序訪問。另外linux將檔案的相關資訊和檔案本身這兩個概念加以區分,這兩者在磁碟上都需要儲存,前者經常又被稱為inode節點,後者才是實際的檔案內容,但必須通過前者才能找到該檔案實際存放的磁碟位置,及操作方法。
vfs使得可以通過使用同一套檔案 i/o系統呼叫即可對 linux 中的任意檔案進行操作而無需考慮其所在的具體檔案系統格式;更進一步,對檔案的操作可以跨檔案系統而執行。如我們可以使用 cp 命令從 vfat 檔案系統格式的硬碟拷貝資料到 ext3 檔案系統格式的硬碟;而這樣的操作涉及到兩個不同的檔案系統。不同的檔案系統塊大小可能不一樣(在超級塊中定義),一般大多數檔案系統使用512b。vfs即虛擬檔案系統是linux檔案系統中的乙個抽象軟體層;因為它的支援,眾多不同的實際檔案系統才能在linux中共存,跨檔案系統操作才能實現。vfs借助它四個主要的資料結構即超級塊、索引節點、目錄項和檔案物件以及一些輔助的資料結構,向linux中不管是普通的檔案還是目錄、裝置、套接字等都提供同樣的操作介面,如開啟、讀寫、關閉等。只有當把控制權傳給實際的檔案系統時,實際的檔案系統才會做出區分,對不同的檔案型別執行不同的操作。由此可見,正是有了vfs的存在,跨檔案系統操作才能執行,unix/linux中的「一切皆是檔案」的口號才能夠得以實現。(不同檔案系統的統一io介面)
如:■什麼是vfs
vfs是軟體, 乙個什麼樣的軟體呢? 是乙個用來管理多個實際檔案系統的軟體
比如linux系統下有兩個實際的檔案系統, 乙個fat32型別磁碟a , 乙個ext3型別磁碟b, 如果我要將a上的乙個檔案1.txt拷貝到b中去,我只需要在中端敲擊命令 cp path1/1.txt path2
就可以了, 而底層會如何做的?
1.根據path1找到對應的1.txt檔案標識(inode 1)
2.呼叫inode 1對應的拷貝函式(此拷貝函式對應的是fat32型別的),將磁碟中的1.txt內容讀入快取記憶體中
3.根據path2找到對應目的地的inode 2
4.呼叫inode 2對應的拷貝函式(此拷貝函式對應的是ext3型別的),將快取記憶體中1.txt內容拷貝到path2指定的目的地
這1-4的過程就是vfs其中的一部分
圖vfs在核心中與其他的核心模組的協同關係
檔案系統的三個操作過程:
註冊: 向核心報到宣告自己能被核心支援。一般在編譯核心的時侯註冊;也可以載入模組的方式手動註冊。註冊過程實際上是將表示各實際檔案系統的資料結構struct file_system_type 例項化。
建立: 以某種方式格式化磁碟的過程就是在其之上建立乙個檔案系統的過程。建立文現系統時,會在磁碟的特定位置寫入關於該檔案系統的控制資訊,即向磁碟寫超級塊。
安裝: 也就是我們熟悉的mount操作,將檔案系統加入到linux的根檔案系統的目錄樹結構上;這樣檔案系統才能被訪問,通過目錄來查詢。
①file_operations與vfs
file_operations結構體中每個函式指標所指向的操作函式都是需要傳進乙個inode表項結構體的;
struct inode 包括很重要的兩個成員:
dev_t i_rdev 裝置檔案的裝置號
struct cdev *i_cdev 代表字元裝置的資料結構,struct inode結構是用來在核心內部表示檔案的。同乙個檔案可以被開啟好多
次,所以可以對應很多struct file,但是只對應乙個struct inode.
open方法根據inode中的裝置號在已註冊的字元裝置驅動中查詢cdev,這個cdev裡的fops才是驅動提供的。它會賦給file結構體中相應成員(file_operations結構體)
(覆蓋了之前的一次賦值),其open方法不為空則呼叫之
②device----driver
add platform_device之後,需要注意的乙個地方是這裡,add是通過系統初始化裡邊呼叫platform_add_devices把所有放置在板級platform_device陣列中的所有platform_device逐次呼叫platform_device_register新增到系統中去,platform_device_register中會呼叫platform_device_add(注意:這個同platform_add_devices有本質區別的),全部add到系統之後,便可以通過platform的操作介面來獲取platform_device中的resource資源,比如位址、中斷號等,以進行request_memregion、ioremap(將resource分配的物理位址對映到kernel的虛擬空間來)和request_irq操作。platform的操作介面包括:
@||| 69 platform_get_irq
@||| 70 platform_get_irq_byname
@||| 71 platform_get_resource
@||| 72 platform_get_resource_byname
add操作是在系統初始化時完成,因此在後續掛在platform虛擬匯流排上的裝置在驅動模組insmod到系統時,驅動**裡邊就可以通過上面函式來獲取對應platform_device的resource,比如在module_init中我們會呼叫plarform_driver_register,這個會引用到platform_driver中的probe函式,而probe函式中則可以進行cdev的初始化及cdev_add的操作,在進行這些操作之前,可以通過get_resource來獲取暫存器物理基位址,然後ioremap到kernel的虛擬空間來,這樣驅動就可以正式操縱改裝置的暫存器了。
至於platform_driver的註冊過程,及何時呼叫probe函式,下面引用一下kernel中的呼叫關係就清晰明了了:
驅動註冊的時候 platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev() 對每個掛在虛擬的platform bus的裝置作 __driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()-& gt;比較strncmp(pdev->name, drv->name, bus_id_size),如果相符就呼叫platform_drv_probe()->driver->probe(),如果probe成 功則繫結該裝置到該驅動
③driver---probe
1.drv->bus->match()首先呼叫驅動或裝置所屬bus匯流排提供的match函式,初步檢測在bus匯流排級別是否能匹配
2.dev->bus->probe()如果不存在,那麼呼叫drv->probe(),更周詳的檢測驅動和裝置的匹配程度.
對於usb系統match函式由usb系統自有的usb_bus_type結構體提供,usb的bus系統不提供probe()函式,必須由使用者
的驅動程式提供
kobj_map函式中雜湊表的實現原理和前面註冊分配裝置號中的幾乎完全一樣,通過要加入系統的裝置的主裝置號major(major=major(dev))來獲得probes陣列的索引值i(i = major % 255),然後把乙個型別為struct probe的節點物件加入到probes[i]所管理的鍊錶中,如圖2-6所示。其中struct probe所在的矩形塊中的深色部分是我們重點關注的內容,記錄了當前正在加入系統的字元裝置物件的有關資訊。其中,dev是它的裝置號,range是從次裝置號開始連續的裝置數量,data是一void *變數,指向當前正要加入系統的裝置物件指標p。圖2-6展示了兩個滿足主裝置號major % 255 = 2的字元裝置通過呼叫cdev_add之後,cdev_map所展現出來的資料結構狀態。
Linux檔案系統學習(三)之結構關係
參考文獻 linux核心設計與實現 3.結構關係 該圖反應的 linux 的檔案系統的體系結構 ext2 jfs 等等 都會匯出一組通用介面,供 vfs 使用。緩衝區快取 buffer cache 會快取檔案系統和相關塊裝置之間的請求。例如,對底層裝置驅動程式的讀寫請求會通過緩衝區快取來傳遞。這就允...
檔案系統學習3 檔案系統相關操作流程
前文中講到了檔案系統有哪幾類操作,這裡對沒類操作檔案系統是如何定址,如果讀寫的進行乙個詳細的說明。1 目錄樹的讀取 所有對檔案的操作,給使用者看來第一步就是得知道這個檔案的目錄,所以首先就需要讀取目錄。每個目錄都是乙個檔案,該檔案存放該目錄下所有檔案的相關資訊,同樣該檔案也有對應的innode。簡答...
Fatfs檔案系統學習
移植過程網上有很多,直接參考就可以了。1 學習過程對api重新理解 f mout f mout fs,0 0 掛載 f mout 0,0 0 解除安裝 一直對解除安裝有錯誤的認識,一直以為解除安裝的時候第乙個形參還是 fs。2 英文長檔名的實現 英文長檔名的實現參考了這個朋友的帖子。define c...