sysfs與普通檔案系統的關係
轉:https://blog.csdn.net/chqsy/article/details/81001600
基礎:
VFS inode 包含檔案訪問許可權、屬主、組、大小、生成時間、訪問時間、最後修改時間等資訊。它是Linux 管理檔案系統的最基本單位,也是檔案系統連線任何子目錄、檔案的橋樑。
核心使用inode結構體在核心內部表示一個檔案。因此,它與表示一個已經開啟的檔案描述符的結構體(即file 檔案結構)是不同的,我們可以使用多個file 檔案結構表示同一個檔案的多個檔案描述符,但此時,所有的這些file檔案結構全部都必須只能指向一個inode結構體
file結構體指示一個已經開啟的檔案(裝置對應於裝置檔案),其實系統中的每個開啟的檔案在核心空間都有一個相應的struct file結構體,它由核心在開啟檔案時建立,並傳遞給在檔案上進行操作的任何函式,直至檔案被關閉。如果檔案被關閉,核心就會釋放相應的資料結構。在核心原始碼中,struct file要麼表示為file,或者為filp(意指“file pointer”), 注意區分一點,file指的是struct file本身,而filp是指向這個結構體的指標
sysfs中的目錄和檔案與kobject和attribute對應,而普通檔案系統是file和inode。sysfs在上層也是通過普通的read(),write()等系統呼叫進行操作的,那麼需要將file_operations轉換成最終的show()/store()。怎麼轉?因為屬性都是屬於kobject的,所以最後的讀寫肯定與kobject有關,先從kobject找找線索,看前面kobject有個屬性——sd,kernfs_node資料結構,是kobject在sysfs的表示。我們從分析這個核心資料結構入手。
kernfs_node
count、active,相關的計數,原子的。
parent,本節點的父節點,這個比較重要,屬性是檔案,父節點才是kobject。
name,節點名字。
rb,紅黑樹節點。
ns、has,名稱空間相關。
dir、symlink、attr,節點的型別,表示該節點是目錄、符號連結還是屬性。三個屬性定義在聯合體中,我們在這關注是的attr。
priv,私有資料,看到私有資料應該推測,有用的東西就在這裡傳遞,事實也是如此,在本節描述的訪問屬性的場景下,kobject就作為私有資料隨kernfs_node傳遞。
flags、mode,與檔案的相關屬性含義一致。
ino,推測是子裝置號。
iattr,節點本身的屬性。
那麼file如何轉換成kernfs_node的呢,類比一下,普通檔案有file和inode,這裡kernfs_node應該是相當於inode,那還應該有代表檔案的結構與之對應,沒錯,是有這個結構。這個結構是什麼,不妨先在kernfs_node中找線索。既然我們的研究物件是屬性,那就看看聯合裡的attr對應的資料結構。
kernfs_elem_attr
ops,對於kernfs的操作函式。
open,開啟的kernfs_node。
size,沒有查到用途,不影響分析。
notify_next,通知kernfs檔案,具體功能不詳,不影響分析。
只關注ops,目前linux中基本所有的操作都獨立抽象出了資料結構,這個資料結構應該是操作kernfs的函式,可能與我們找的答案有關
kernfs_ops
atomic_write_len,寫是以kernel page為邊界的,如果沒有設定atomic_write_len,超過PAGE_SIZE的寫操作會被分成幾個操作進行。如果設定了atomic_write_len,那麼超過這個設定值的寫操作,atomic_write_len以內的部分是原子寫,超過的部分直接返回-E2BIG。
prealloc,設定了用mmap,不設定用read/write。因為read/wirte有自己的buf,與prealloc的buf不相容。
seq_show、seq_start、seq_next、seq_stop,順序檔案操作。下面會詳細分析。這裡需要關注他們的引數。
read、write、mmap,讀,寫,記憶體對映函式,這裡關注他們的引數。
看一下seq_xx和read的原型,引數分別為seq_file和kernfs_open_file。從名字上看kernfs_open_file和kernfs_node的關係,很像file和inode的關係。不妨先看看kernfs_open_file。
kernfs_open_file
kn,所屬的目錄節點。
file,代表開啟檔案。
priv,私有資料結構。
mutex,互斥體。
list,確實沒有查到在哪裡呼叫,暫時推測不出用途,不影響分析。
pralloc_buf,mmap使用。
atomic_write_len,同kernfs_elem_attr。
mmaped,是否已經進行了ioremap。
vm_ops,虛擬記憶體管理操作。
從核心類的成員可能得出這樣的推測,kernfs_open_file.file儲存普通檔案的file指標,在進行讀寫是用container_of()從file裡獲得kernfs_open_file結構體。以前的核心可能是這麼做的,但是現在不是這樣的。這裡要提到上面數的另一個核心資料結構seq_file。
seq_file
seq_file是為proc檔案系統設計的,來歷是這樣的,由於procfs的預設操作函式只使用一頁的快取,在處理較大的proc檔案時就有點麻煩,並且在輸出一系列結構體中的資料時也比較不靈活,需要自己在read_proc函式中實現迭代,容易出現Bug。所以核心黑客們對一些/proc程式碼做了研究,抽象出共性,最終形成了seq_file(Sequence file:序列檔案)介面。 這個介面提供了一套簡單的函式來解決以上proc介面程式設計時存在的問題,使得程式設計更加容易,降低了Bug出現的機會。
不只是proc,在需要建立一個由一系列資料順序組合而成的虛擬檔案或一個較大的虛擬檔案時,推薦使用seq_file介面。這正是符合bin_attribute的場景。看一下seq_file的結構。
這個結構的成員與file差不多,基本不用關心,因為他們都是使用op成員定義的方法操作的,一定意義上可以看作私有成員,圖中沒有這麼畫。
需要注意的是結構裡有個private,這麼多回了應該有這個意識了,看見private就有可能跟我們結構掛上關係。事實也是如此。kernfs_open_file的指標是放到seq_file的private中的
從file到attribute
至此只剩seq_file如何與普通的file聯絡在一起了,那就簡單了,跟大部分驅動程式是一樣的,seq_file包含在file的private_data中。整合上述關係,可以在下面類圖中表示。
從file找到sysfs的屬性檔案,經歷了很長的鏈條,這個其實是多型,由於c語言的特性,linux驅動程式用了很費勁的方式實現了多型。
上邊這個可能還是抽象一點,把ops族物件加入跟為直觀,忽略一些中間環節。
從操作上,從VFS的fs到sysfs經歷了file_operations域,kernfs_ops域和最終的sys_ops域的轉換