首页 > 代码库 > 驱动笔记 - ioctl

驱动笔记 - ioctl

#include <linux/ioctl.h>

定义命令
_IO(type,nr) 没有参数的命令
_IOR(type,nr,datatype) 从驱动中读数据
_IOW(type,nr,datatype) 写数据到驱动
_IOWR(type,nr,datatype) 双向传送,type和number成员作为参数被传递
例:
#define MEM_IOC_MAGIC ‘m‘
#define MEM_IOCSET _IOW(MEM_IOC_MAGIC,0,int)
#define MEM_IOCGQSET _IOR(MEM_IOC_MAGIC,1,int)

unlock_ioctl一般使用switch,不匹配的命令通常返回-EINVAl

应用层调用ioctl

#include <linux/ioctl.h>
ioctl(int fd,int command, (char*)argstruct)

参数检测(检测是否有效)
int access_ok(int type, const void *addr, unsigned long size)
一般把addr强制转化为(void __user *)
type:VERIFY_READ或者VERIFY_WRITE
size:操作的大小
返回值:1成功 0失败
access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd))
access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));

不需要检测(函数中自带有检测)
unsigned long copy_from_user (void * to, const void __user * from, unsigned long n) //此函数自带access_ok
unsigned long copy_to_user (void __user * to, const void * from, unsigned long n) //此函数自带access_ok
get_user
put_user

需要检测
__get_user
__get_user(tmp, (int __user *)arg);

__put_user

 

例:

long ioctl(struct file *file, unsigned int cmd, unsigned long arg){	int err = 0,tmp;	int retval = 0;	if(_IOC_TYPE(cmd) != MEMDEV_MAGIC)		return -ENOTTY;	if(_IOC_NR(cmd) > MEMDEV_MAXNR)		return -ENOTTY;	if(_IOC_DIR(cmd) & _IOC_READ)		err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));	else if(_IOC_DIR(cmd) & _IOC_WRITE)		err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));	if(err)		return -EFAULT;	switch(cmd)	{		case MEMDEV_TELL:			printk(KERN_ALERT "Your call MEMDEV_TELL.\n");			break;		case MEMDEV_RECEIVE:			if(retval = __get_user(tmp, (int __user *)arg) == 0)			{				printk(KERN_ALERT "memdev receive number is %d\n",tmp);			}			else				printk(KERN_ALERT "No receive.\n");			break;		case MEMDEV_SET:			tmp = 110;			if(retval = __put_user(tmp, (int __user *)arg) == 0)			{				printk(KERN_ALERT "memdev send number is %d\n", tmp);			}			else				printk(KERN_ALERT "Sent error\n");			break;		default:			return -ENOTTY;	}	return retval;}

  

 

驱动笔记 - ioctl