使用ioctl與核心交換資料

2021-04-15 17:22:42 字數 3647 閱讀 7196

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/a**/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是很多核心操作結構的乙個成員函式,如檔案操作結構struct fi...

使用ioctl和核心交換資料

1.前言 使用ioctl系統呼叫是使用者空間向核心交換資料的常用方法之一,從ioctl這個名稱上看,本意是針對i o裝置進行的控制操作,但實際並不限制是真正的i o裝置,能是所有乙個核心裝置即可。2.基本過程 在核心空間中ioctl是非常多核心操作結構的乙個成員函式,如檔案操作結構struct fi...

linux ioctl與核心交換資料

1.前言 使用ioctl系統呼叫是使用者空間向核心交換資料的常用方法之一,從ioctl這個名稱上看,本意是針對i o裝置進行的控制操作,但實際並不限制是真正的i o裝置,可以是任何乙個核心裝置即可。2.基本過程 在核心空間中ioctl是很多核心操作結構的乙個成員函式,如檔案操作結構struct fi...