linux 设备驱动之IOCTRL

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(& valargp, 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)