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


4. 系統調用
系統調用是內核提供給應用程式的介面,應用對底層硬體的操作大部分都是通過調用系統調用來完成的,
例如得到和設置系統時間,就需要分別調用 gettimeofday 和 settimeofday 來實現。
事實上,所有的系統調用都涉及到內核與應用之間的資料交換,
如文件系統操作函數 read 和 write,設置和讀取網路協定棧的 setsockopt 和 getsockopt。
本節並不是講解如何增加新的系統調用,而是講解如何利用現有系統調用來實現用戶的資料傳輸需求。
一般地,用戶可以建立一個為設備來作為應用與內核之間進行資料交換的渠道,最通常的做法是使用字元設備,
具體實現方法是:
I. 定義對字元設備進行操作的必要函數並設置結構 struct file_operations
結構 struct file_operations 非常大,對於一般的資料交換需求,
只定義 open, read, write, ioctl, mmap 和 release 函數就足夠了,
它們實際上對應於用戶態的文件系統操作函數 open, read, write, ioctl, mmap 和 close。
這些函數的原型示例如下:
ssize_t exam_read (struct file * file, char __user * buf, size_t count, loff_t * ppos)
ssize_t exam_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
int exam_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long argv)
int exam_mmap(struct file *, struct vm_area_struct *)
int exam_open(struct inode * inode, struct file * file)
int exam_release(struct inode * inode, struct file * file)

在定義了這些操作函數後需要定義並設置結構struct file_operations
struct file_operations exam_file_ops = {
.owner = THIS_MODULE,
.read = exam_read,
.write = exam_write,
.ioctl = exam_ioctl,
.mmap = exam_mmap,
.open = exam_open,
.release = exam_release,
};
II. 註冊定義的偽字元設備並把它和上面的 struct file_operations 關聯起來:
int exam_char_dev_major;
exam_char_dev_major = register_chrdev(0, "exam_char_dev", &exam_file_ops);
注意,函數 register_chrdev 的第一個參數
如果為 0,表示由內核來確定該註冊為字元設備的主設備號,這是該函數的返回為實際分配的主設備號,
如果返回小於 0,表示註冊失敗。
因此,用戶在使用該函數時必須判斷返回值以便處理失敗情況。
為了使用該函數必須包含標頭檔 linux/fs.h。

在 program-examples 中給出了一個使用這種方式實現用戶態與內核態資料交換的典型例子,
它包含了三個文件:
標頭檔 syscall-exam.h 定義了 ioctl 命令,
.c文件 syscall-exam-user.c 為用戶態應用,它通過文件系統操作函數 mmap 和 ioctl 來與內核態模組交換資料,
.c文件 syscall-exam-kern.c 為內核模組,它實現了一個為字元設備,以便與用戶態應用進行資料交換。
為了正確運行應用程式 syscall-exam-user,需要在插入模組 syscall-exam-kern 後創建該實現的為字元設備,
用戶可以使用下面命令來正確創建設備:
$ mknod /dev/mychrdev c `dmesg | grep "char device mychrdev" | sed 's/.*major is //g'` 0
然後用戶可以通過 cat 來讀寫 /dev/mychrdev,
應用程式 syscall-exam-user 則使用 mmap 來讀數據並使用 ioctl 來得到該字元設備的資訊以及裁減資料內容,
它只是示例如何使用現有的系統調用來實現用戶需要的資料交互操作。
下面是作者運行該模組的結果示例:
$ insmod ./syscall-exam-kern.ko
char device mychrdev is registered, major is 254
$ mknod /dev/mychrdev c `dmesg | grep "char device mychrdev" | sed 's/.*major is //g'` 0
$ cat /dev/mychrdev
$ echo "abcdefghijklmnopqrstuvwxyz" > /dev/mychrdev
$ cat /dev/mychrdev
abcdefghijklmnopqrstuvwxyz
$ ./syscall-exam-user
User process: syscall-exam-us(1433)
Available space: 65509 bytes
Data len: 27 bytes
Offset in physical: cc0 bytes
mychrdev content by mmap:
abcdefghijklmnopqrstuvwxyz
$ cat /dev/mychrdev
abcde
$

arrow
arrow
    全站熱搜

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