標籤:
linux 裝置驅動之IOCTRL
1,where come from?ioctrl(或者說unlocked_ioctl/compat_ioctl)是file_operations結構體的函數指標struct file_operations {
...
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
...
};
2,who am i在使用者空間,ioctl是一個系統調用, 作用於一個檔案描述符; 它接收一個確定要進行的命令的數字和(可選地)另一個參數, 常常是一個指標.這些命令可以核心空間和使用者空間之間進行資料互動。這些命令可以從驅動拷貝相關的資料結構到使用者空間。
3,所謂的命令(CMD)是什嗎?在Kernel層,對於一個32bit的系統,分成了4個域,分段如下@include/uapi/asm-generic/ioctl.h
2bits(讀寫區)_IOC_DIRBITS |
14bits(資料大小區)_IOC_SIZEBITS |
8bits(Magic)_IOC_TYPEBITS |
8bits(命令序號)_IOC_NRBITS |
31 30/29 28 ... 17 16/15 14 ... 9 8/7 6 ... 1 0所謂的Magic區,無非就是不同驅動使用一個字母來標識。比如LDD3,#define SCULL_IOC_MAGIC ‘k‘#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1, int)
4,為什麼不使用“粗暴”的,一個unsigned int值來代替一個cmd?我認為,使用一個32bit的不同位來表示一個cmd,能包含更多的資訊,節省了記憶體
5,如何使用?5.1,在應用程式層和Kernel使用同一個CMD定義的h檔案,來使用cmd在應用程式層:#define REMOTE_IOC_SET_REPEAT_KEY_MAPPING _IOW_BAD(‘I‘,20,sizeof(short))在Kernel層:#define REMOTE_IOC_SET_REPEAT_KEY_MAPPING _IOW_BAD(‘I‘,20,sizeof(short))
5.2,在應用程式層調用這個命令,device_fd為對應的裝置檔案 val = (i<<16) | repeat_key_map[i];
ioctl(device_fd, REMOTE_IOC_SET_REPEAT_KEY_MAPPING, &val); 在Kernel層,將會做相應的處理先把&val傳進來的值copy_from_user,然後使用這個val值static long remote_config_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
{
void __user *argp = (void __user *)args;
ret = copy_from_user(&val, argp, sizeof(unsigned long));case REMOTE_IOC_SET_REPEAT_KEY_MAPPING:
remote->key_repeat_map[remote->map_num][val >> 16] = val & 0xffff;
break;...}
6,另外:IOCTL相關的宏,讀ioctl.h就知道了。#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
linux 裝置驅動之IOCTRL