close

原文網址 http://blog.xuite.net/tzeng015/twblog/113272242

 

在 Linux 下用戶空間與內核空間資料交換的九種方式,包括
http://svn.openfoundry.org/vwebsdk/Reference/switch.txt

 

在 Linux 下用戶空間與內核空間資料交換的九種方式,包括
1. 內核啟動參數 (__setup)
2. 模組參數與 sysfs (module_param)
3. sysctl (register_sysctl_table)
4. 系統調用
5. netlink 是一種雙向的資料交換方式,它使用起來非常簡單高效,特別是它的廣播特性在一些應用中非常方便。
6. procfs 一般用于向用戶保留少量的數據訊息,或用戶透過它設置內核變量從而控制內核行為。
7. seq_file 是單向的,即只能向內核傳遞,而不能從內核獲取,其餘的均可以進行雙向資料交換,即既可以從用戶應用傳遞給內核,有可以從內核傳遞給應用態應用。
實際上倚賴于 procfs,因此為了使用 seq_file,必須使內核支持 procfs。
8. debugfs 用于內核開發者調試使用,它比其他集中模式都方便,但是僅用于簡單類型的變量處理。
9. relayfs 是一種非常複雜的數據交換模式,要想準確使用並不容易,但是如果使用得當,它遠比 procfs 和 seq_file 功能強大。

 

8. debugfs
內核開發者經常需要向用戶空間應用輸出一些調試訊息,在穩定的系統中可能根本不需要這些調試訊息,
但是在開發過程中,為了搞清楚內核的行為,調試信息非常必要,printk可能是用的最多的,但它並不是最好的,
調試訊息只是在開發中用于調試,而 printk 將一直輸出,因此開發完畢后需要清除不必要的 printk 語句,
另外如果開發者希望用戶空間應用能夠改變內核行為時,printk就無法實現。
因此,需要一種新的機製,那只有在需要的時候使用,它在需要時透過在一個虛擬文件系統中創建一個或多個文件來向用戶空間應用提供調試訊息。
有幾種模式可以實現上述要求︰
使用 procfs 在 /proc 創建文件輸出調試訊息,但是 procfs 對于大于一個內存頁(對于x86是4K)的輸出比較麻煩,而且速度慢,有時回出現一些意想不到的問題。
使用 sysfs (2.6內核引入的新的虛擬文件系統),在很多情況下,調試訊息可以存放在那裡,
但是 sysfs 主要用于系統管理,它希望每一個文件對應內核的一個變量,如果使用它輸出複雜的數據架構或調試訊息是非常困難的。
使用 libfs 創建一個新的文件系統,該方法極其靈活,開發者可以為新文件系統設置一些規則,
使用 libfs 使得創建新文件系統更加簡單,但是仍然超出了一個開發者的想像。
為了使得開發者更加容易使用這樣的機製,Greg Kroah-Hartman開發了debugfs(在2.6.11中第一次引入),
它是一個虛擬文件系統,專門用于輸出調試訊息,該文件系統非常小,很容易使用,可以在配置內核時選擇是否構件到內核中,
在不選擇它的情況下,使用它提供的API的內核部分不需要做任何改動。

使用 debugfs 的開發者首先需要在文件系統中創建一個目錄,下面函數用于在 debugfs 文件系統下創建一個目錄︰
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
參數 name 是要創建的目錄名,
參數 parent 指定創建目錄的父目錄的 dentry, 如果為NULL,目錄將創建在 debugfs 文件系統的根目錄下。
如果返回為 -ENODEV, 表示內核沒有把 debugfs 編譯到其中,
如果返回為 NULL, 表示其他類型的創建失敗,如果創建目錄成功,返回指向該目錄對應的 dentry 列舉的指針。

下面函數用于在 debugfs 文件系統中創建一個文件:
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, struct file_operations *fops);
name 指定要創建的文件名,
mode 指定該文件的訪問許可,
parent 指向該文件所在目錄,
data 為該文件特定的一些數據,
fops 為實現下該文件上進行文件操作的 fiel_operations 架構指針,
在很多情況下,由 seq_file (前面章節已經講過)提供的文件操作實現就足夠了,
因此使用 debugfs 很容易,當然在一些情況下,開發者可能僅需要使用用戶應用可以控制的變量來調試,

debugfs 也提供了4個這樣的API方便開發者使用︰
struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, u16 *value);
struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, u32 *value);
struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value);
參數 name 和 mode 指定文件名和訪問許可,參數 value 為需要讓用戶應用控制的內核變量指針。

當內核模塊卸載時, debugfs 並不會自動清除該模塊創建的目錄或文件,因此對于創建的每一個文件或目錄,開發者必須調用下面函數清除:
void debugfs_remove(struct dentry *dentry);
參數 dentry 為上面創建文件和目錄的函數返回的 dentry 指針。

在 program-examples 中給出了一個使用 debufs 的示例模塊 debugfs_exam.c, 為了保證該模塊正確營運,必須讓內核支持 debugfs,
debugfs 是一個調試功能,因此它位于主菜單 Kernel hacking, 並且必須選擇 Kernel debugging 選項才能選擇,它的選項名稱為 Debug Filesystem。

為了在用戶態使用 debugfs, 用戶必須 mount 它,下面是在作者系統上的使用輸出:
$ mkdir -p /debugfs
$ mount -t debugfs debugfs /debugfs
$ insmod ./debugfs_exam.ko
$ ls /debugfs
debugfs-exam
$ ls /debugfs/debugfs-exam
u8_var u16_var u32_var bool_var
$ cd /debugfs/debugfs-exam
$ cat u8_var
0
$ echo 200 > u8_var
$ cat u8_var
200
$ cat bool_var
N
$ echo 1 > bool_var
$ cat bool_var
Y

arrow
arrow

    橘 發表在 痞客邦 留言(0) 人氣()