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 功能強大。


6. procfs
procfs 是比較老的一種用戶態與內核態的數據交換模式,內核的很多數據都是透過這種模式保留給用戶的,
內核的很多參數也是透過這種模式來讓用戶方便設置的。
除了sysctl 保留到 /proc 下的參數,procfs 提供的大部分內核參數是只讀的。
實際上,很多應用嚴重地倚賴于 procfs, 因此它幾乎是必不可少的組件。
前面部分的幾個例子實際上已經使用它來保留內核數據,但是並沒有講解如何使用,本節將講解如何使用 procfs。
Procfs 提供了如下API:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
該函數用于創建一個正常的 proc 列舉,
參數 name 給出要建立的 proc 列舉的名稱,
參數 mode 給出了建立的該 proc 列舉的訪問權限,
參數 parent 指定建立的 proc 列舉所在的目錄。
如果要在 /proc下建立 proc 列舉, parent 應當為 NULL.
否則它應當為 proc_mkdir 返回的 struct proc_dir_entry 結構的指針。

extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
該函數用于刪除上面函數創建的 proc 列舉,
參數name給出要刪除的 proc 列舉的名稱,
參數parent指定建立的 proc 列舉所在的目錄。

struct proc_dir_entry *proc_mkdir(const char * name, struct proc_dir_entry *parent)
該函數用于創建一個 proc 目錄,
參數 name 指定要創建的 proc 目錄的名稱,
參數 parent 指定 proc 目錄所在的目錄。

extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, struct proc_dir_entry *parent);

struct proc_dir_entry *proc_symlink(const char * name, struct proc_dir_entry * parent, const char * dest)
該函數用于建立一個 proc 列舉的符號連接,
參數 name 給出要建立的符號連接 proc 列舉的名稱,
參數 parent 指定符號連接所在的目錄,
參數 dest 指定連接到的 proc 列舉名稱。

struct proc_dir_entry *create_proc_read_entry(const char *name,
mode_t mode, struct proc_dir_entry *base,
read_proc_t *read_proc, void * data)

struct proc_dir_entry *create_proc_info_entry(const char *name,
mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
該函數用于創建一個info型的 proc 列舉,
參數 name 給出要建立的 proc 列舉的名稱,
參數 mode 給出了建立的該 proc 列舉的訪問權限,
參數 base 指定建立的 proc 列舉所在的目錄,
參數 get_info 指定該 proc 列舉的get_info操作函數。

struct proc_dir_entry *proc_net_create(const char *name,
mode_t mode, get_info_t *get_info)

struct proc_dir_entry *proc_net_fops_create(const char *name,
mode_t mode, struct file_operations *fops)

void proc_net_remove(const char *name)
該函數用于刪除前面兩個函數在 /proc/net 目錄下創建的 proc 列舉。
參數 name 指定要刪除的 proc 名稱。

除了這些函數,值得一提的是架構 struct proc_dir_entry,為了創建一了可寫的 proc 列舉並指定該 proc 列舉的寫操作函數,
必須設置上面的這些創建 proc 列舉的函數返回的指針指向的 struct proc_dir_entry 架構的 write_proc 字段,
並指定該 proc 列舉的訪問權限有寫權限。
為了使用這些界面函數以及架構 struct proc_dir_entry,用戶必須在模塊中包含標頭檔 linux/proc_fs.h。
在 program-examples 中出了 procfs 示例程序 procfs_exam.c, 它定了三個 proc 文件列舉和一個 proc 目錄列舉,或者:
$ ls /proc/myproctest
aint astring bigprocfile
$

讀者可以透過 cat 和 echo 等文件操作函數來查看和設置這些 proc 文件。
特別需要指出, bigprocfile 是一個大文件(超過一個內存頁),對于這種大文件, procfs 有一些限制,
因為它提供的緩存,只有一個頁,因此必須特別小心,並對超過頁的部分做特別的考慮,處理起來比較複雜並且很容易出錯,
所有 procfs 並不適合于大數據量的輸入輸出,后面一節 seq_file 就是因為這一缺陷而設計的,
當然 seq_file 倚賴于 procfs 的一些基礎功能。

arrow
arrow
    全站熱搜

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