ioctl 字元裝置的控制技術

2021-07-11 17:12:10 字數 4068 閱讀 5551

字元裝置的控制

1. 字元裝置控制理論

1.1 作用

大部分驅動程式除了需要提供讀寫裝置的能力外,還需要具備控制裝置的能力。比如:改變波特率

1.2 應用程式介面

在使用者空間,使用ioctl系統呼叫來控制裝置,原型如下:

int  ioctl(int fd, unsigned long cmd, ...)

fd: 要控制的裝置檔案描述符

cmd: 傳送給裝置的控制命令

...: 第三個引數是可選的引數,存在與否依賴於控制命令(第二個引數)

1.3 裝置驅動方法

2. 字元裝置控制實現

2.1 定義命令 

命令其實質而言就是乙個整數,但為了讓這個整數具備更好的可讀性,我們通常會把這個整數分為幾個段,類             型(8位),序號, 引數傳送方向,引數長度

type(型別/幻數):表明這是屬於哪個裝置的命令

number(序號):用來區分同一裝置的不同命令

direction: 引數傳送的方向,可能的值是_ioc_none(沒有資料傳輸),_ioc_read, _ioc_write(向裝置讀寫           引數)

size : 引數長度

linux系統提供了下面的巨集來幫助定義命令:

*_io(type, nr) : 不帶引數的命令

*_ior(type, nr, datatype) : 從裝置中讀取引數的命令

*_iow(type, nr, datatype) : 向裝置寫入引數的命令

例如:#define mem_magic  'm' //定義幻數

#define mem_set  _iow(mem_magic, 0, int)

2.2 實現裝置方法

unlocked_ioctl函式的實現通常是根據命令執行的乙個switch語句。但是,當命令號不能匹配任何乙個裝置所支           持的命令時, 返回 -einval

程式設計模型:

switch cmd:

case  命令a:

//執行a所對應的操作

case  命令b:

//執行b對應的操作

defaule:

return -einval;

例項**分析來實現ioctl:

這裡的memdev.c還是接著上篇的基礎上改的

#include #include #include #include #include #include #include #include #include "memdev.h"

int dev1_registers[5];

int dev2_registers[5];

struct cdev cdev;

dev_t devno;

/*檔案開啟函式*/

int mem_open(struct inode *inode, struct file *filp)

/*檔案釋放函式*/

int mem_release(struct inode *inode, struct file *filp)

/*讀函式*/

static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)

else

return ret;

}/*寫函式*/

static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)

return ret;

}/* seek檔案定位函式 */

static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)

if ((newpos<0) || (newpos>5*sizeof(int)))

return -einval;

filp->f_pos = newpos;

return newpos;

}//裝置控制函式

long mem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

return 0;

}/*檔案操作結構體*/

static const struct file_operations mem_fops =

;/*裝置驅動模組載入函式*/

static int memdev_init(void)

/*模組解除安裝函式*/

static void memdev_exit(void)

module_license("gpl");

module_init(memdev_init);

module_exit(memdev_exit);

memdev.h

#define mem_magic 'm' //定義乙個幻數,而長度正好和asc碼長度一樣為8位,所以這裡定義個字元

#define mem_restart _io(mem_magic, 0) //第乙個命令是重啟的命令,重啟的命令不帶引數 第一命令這裡序號定義成0

#define mem_set _iow(mem_magic, 1, int) //設定引數命令 序號為1, 型別為int

測試應用程式mem_ctl.c

#include#include#include#include#include "memdev.h"

int main()

makefile

obj-m := memdev.o

kdir := /home/kernel/linux-ok6410

all:

make -c $(kdir) m=$(pwd) modules cross_compile=arm-linux- arch=arm

clean:

rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order

這裡ioctl函式原型可以檢視核心原始碼fs.h(/include/linux目錄下)檔案

然後這次採用靜態編譯mem_ctl.c檔案 arm-linux-gcc -static -o memctl (這裡採用靜態編譯上面博文有說道)

由於掛載了整個rootfs目錄,這裡編譯產生的檔案會同步到我的開發板

安裝裝置驅動模組,然後cat /proc/device 檢視裝置驅動程式的主裝置號

然後建立裝置檔案,這樣我們的應用程式就可以通過這個裝置檔案來訪問裝置了(當然這裡我們的裝置是虛擬出來的字元裝置,不過麻雀雖小五臟俱全)

mknod memdev0 c 252 0 (執行該命令)

memdevo是我們給字元裝置取的名字, 252是該字元裝置的裝置號,

這裡可以看到/dev目錄下就會產生memdev0這個裝置檔案了,執行mem_clt應用程式

至此ioctl字元裝置的控制就over了!

ioctl裝置控制 筆記

使用者層 原型 int ioctl int fd,unsigned long cmd,說明 其中原點表示可選引數,存在與否依賴於控制命令 第二個引數 是否涉及到與裝置的資料互動 驅動層 原型 int 說明 cmd引數是從使用者層傳下來,可選引數arg以乙個unsigned long 的形式傳遞 為乙...

字元裝置控制技術

1 大部分驅動程式除了需要提供讀寫裝置的能力,還應具備控制裝置的能力。2 在使用者空間,使用ioctl系統呼叫來控制裝置。函式原型 int ioctl int fd,unsigned long cmd,fd 要控制的裝置檔案描述符 cmd 傳送給裝置的控制命令 第3個引數是可選的引數,存在與否是依賴...

裝置控制介面(ioctl 函式)

int ioctl struct inode struct file unsigned int,unsigned long 這是驅動程式裝置控制介面函式 ioctl函式 的核心原型定義,struct inode 和 struct file 描述了操作的檔案,unsigned int 描述了ioctl...