1. 前言
使用ioctl系統呼叫是使用者空間向核心交換資料的常用方法之一,從ioctl這個名稱上看,本意是針對i/o裝置進行的控制操作,
但實際並不限制是真正的i/o裝置,可以是任何乙個核心裝置即可。
2. 基本過程
在核心空間中ioctl是很多核心操作結構的乙個成員函式,如檔案操作結構struct file_operations(include/linux/fs.h)、
協議操作結構struct proto_ops(include/linux/net.h)等、tty操作結構struct tty_driver(include/linux/tty_driver.h)等,
而這些操作結構分別對應各種核心裝置,只要在使用者空間開啟這些裝置,如i/o裝置可用open(2)開啟,網路協議可用socket(2)開啟等,
獲取乙個檔案描述符後,就可以在這個描述符上呼叫ioctl(2)來向核心交換資料。
3. ioctl(2)
ioctl(2)函式的基本使用格式為:
int ioctl(int fd, int cmd, void *data)
第乙個引數是檔案描述符;cmd是操作命令,一般分為get、set以及其他型別命令,get是使用者空間程序從核心讀資料,set是使用者空間程序向核心寫資料,
cmd雖然是乙個整數,但是有一定的引數格式的,下面再詳細說明;第三個引數是資料起始位置指標,
cmd命令引數是個32位整數,分為四部分:
dir(2b) size(14b) type(8b) nr(8b)
詳細定義cmd要包括這4個部分時可使用巨集_ioc(dir,type,nr,size)來定義,而最簡單情況下使用_io(type, nr)來定義就可以了,這些巨集都在include/asm/ioctl.h中定義
本文cmd定義為:
#define newchar_ioc_magic 'm'
#define newchar_set _io(newchar_ioc_magic, 0)
#define newchar_get _io(newchar_ioc_magic, 1)
#define newchar_ioc_maxnr 1
要定義自己的ioctl操作,可以有兩個方式,一種是在現有的核心**中直接新增相關**進行支援,比如想通過socket描述符進行 ioctl操作,
可在net/ipv4/af_inet.c中的inet_ioctl()函式中新增自己定義的命令和相關的處理函式,重新編譯核心即可,不過這種方法一般不推薦;
第二種方法是定義自己的核心裝置,通過裝置的ioctl()來操作,可以編成模組,這樣不影響原有的核心,這是最通常的做法。
4. 核心裝置
為進行ioctl操作最通常是使用字元裝置來進行,當然定義其他型別的裝置也可以。在使用者空間,可使用mknod命令建立乙個字元型別裝置檔案,
假設該裝置的主裝置號為123,次裝置號為0:mknode /dev/newchar c 123 0
如果是程式設計的話,可以用mknode(2)函式來建立裝置檔案。
建立裝置檔案後再將該裝置的核心模組檔案插入核心,就可以使用open(2)開啟/dev/newchar檔案,然後呼叫ioctl(2)來傳遞資料,最後用close(2)關閉裝置。
而如果核心中還沒有插入該裝置的模組,open(2)時就會失敗。
由於核心記憶體空間和使用者記憶體空間不同,要將核心資料拷貝到使用者空間,要使用專用拷貝函式copy_to_user();要將使用者空間資料拷貝到核心,要使用copy_from_user()。
要最簡單實現以上功能,核心模組只需要實現裝置的open, ioctl和release三個函式即可,
下面介紹程式片斷:
static int newchar_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
static int newchar_open(struct inode *inode, struct file *filep);
static int newchar_release(struct inode *inode, struct file *filep);
// 定義檔案操作結構,結構中其他元素為空
struct file_operations newchar_fops =
;// 定義要傳輸的資料塊結構
struct newchar;
#define major_dev_num 123
#define device_name "newchar"
開啟裝置,非常簡單,就是增加模組計數器,防止在開啟裝置的情況下刪除模組,
當然想搞得複雜的話可進行各種限制檢查,如只允許指定的使用者開啟等:
static int newchar_open(struct inode *inode, struct file *filep)
關閉裝置,也很簡單,減模組計數器:
static int newchar_release(struct inode *inode, struct file *filep)
進行ioctl呼叫的基本處理函式
static int newchar_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg)
break;
case knewchar_get:
// get操作通常會在資料緩衝區中先傳遞部分初始值作為資料查詢條件,獲取全部
// 資料後重新寫回緩衝區
// 當然也可以根據具體情況什麼也不傳入直接向核心獲取資料
}break;
}return ret;
}模組初始化函式,登記字元裝置
static int __init _init(void)
return 0;
}模組退出函式,登出字元裝置
static void __exit _cleanup(void)
module_init(_init);
module_exit(_cleanup);
5. 結論
用ioctl()在使用者空間和核心空間傳遞資料是最常用方法之一,比較簡單方便,而且可以在同乙個ioctl中對不同的命令傳送不同的資料結構,
本文只是為描述方便而在不同命令中使用了相同的資料結構。
使用ioctl與核心交換資料
1.前言 使用ioctl 系統呼叫是使用者空間向核心交換資料的常用方法之一,從 ioctl 這個名稱上看,本意是針對 i o裝置進行的控制操作,但實際並不限制是真正的 i o裝置,可以是任何乙個核心裝置即可。2.基本過程 在核心空間中 ioctl 是很多核心操作結構的乙個成員函式,如檔案操作結構 s...
使用ioctl與核心交換資料
1.前言 使用ioctl系統呼叫是使用者空間向核心交換資料的常用方法之一,從ioctl這個名稱上看,本意是針對i o裝置進行的控制操作,但實際並不限制是真正的i o裝置,可以是任何乙個核心裝置即可。2.基本過程 在核心空間中ioctl是很多核心操作結構的乙個成員函式,如檔案操作結構struct fi...
接入交換機,匯聚交換機,核心交換機
通常將網路中直接面向使用者連線或訪問網路的部分稱為接入層,將位於接入層和核心層之間的部分稱為分布層或匯聚層。接入交換機一般用於直接連線電腦,匯聚交換機一般用於樓宇間。匯聚相對於乙個區域性或重要的中轉站,核心相當於乙個出口或總彙總。原來定義的匯聚層的目的是為了減少核心的負擔,將本地資料交換機流量在本地...