首页 > 代码库 > 驱动笔记 - 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