1. 程式人生 > >Linux文件系統學習(一)之相關概念???

Linux文件系統學習(一)之相關概念???

正是 range 不同的 struct pan 根據 inode 存在 opera

“一切皆是文件”是 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表項結構體的;

②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

kobj_map函數中哈希表的實現原理和前面註冊分配設備號中的幾乎完全一樣,通過要加入系統的設備的主設備號major(major=MAJOR(dev))來獲得probes數組的索引值ii = 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文件系統學習(一)之相關概念???