字元裝置的控制
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...