IO IOC IOR IOW等一些宏定义的解析

// include/asm-generic/ioctl.h 头文件

#define _IOC_NRBITS8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
#define _IOC_NRSHIFT0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)/** Direction bits.*/
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
#define _IOC(dir,type,nr,size) \
(((dir)  << _IOC_DIRSHIFT) | \        //dir <<30
((type) << _IOC_TYPESHIFT) | \   //type << 8
((nr)   << _IOC_NRSHIFT) | \         //nr << 0
((size) << _IOC_SIZESHIFT))       //size << 16


可以看出IOC返回的是一个32bit的数据,具体type dir nr size的方向位置如下:




总结:

我们只需要设置type这个数字然后定义nr这个值的大小,并设定每个值的作用即可,模仿scull的定义


#define TEST_IOC_MAGIC 0x54 //type =0x54
#define TEST_IOCSQUANTUM _IOW(TEST_IOC_MAGIC,  1, int)//0x40045401 
//dir size type nr 组合成32bit的数据,一个CMD
#define TEST_IOCSQSET    _IOW(TEST_IOC_MAGIC,  2, int) //0x40045402
#define TEST_IOCTQUANTUM _IO(TEST_IOC_MAGIC,   3)      //0x00005403
#define TEST_IOCTQSET     _IO(TEST_IOC_MAGIC,   4)    //0x00005404
#define TEST_IOCGQUANTUM _IOR(TEST_IOC_MAGIC,  5, int)//0x80045405
#define TEST_IOCGQSET    _IOR(TEST_IOC_MAGIC,  6, int)//0x80045406
#define TEST_IOCQQUANTUM  _IO(TEST_IOC_MAGIC,   7)  //0x00005407
#define TEST_IOCQQSET    _IO(TEST_IOC_MAGIC,   8)      //0x00005408
#define TEST_IOCXQUANTUM _IOWR(TEST_IOC_MAGIC, 9, int)//0xC0045409
#define TEST_IOCXQSET    _IOWR(TEST_IOC_MAGIC,10, int)//0xC004540A
#define TEST_IOCHQUANTUM _IO(TEST_IOC_MAGIC,  11)      //0x0000540B 
#define TEST_IOCHQSET     _IO(TEST_IOC_MAGIC,  12)      //0x0000540C


//附录:scull ioctl函数的源码:

int scull_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)
{int err = 0, tmp;
int retval = 0;/*
* extract the type and number bitfields, and don't decode
* wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
*/
if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC) return -ENOTTY;
if (_IOC_NR(cmd) > SCULL_IOC_MAXNR) return -ENOTTY;/*
* the direction is a bitmask, and VERIFY_WRITE catches R/W
* transfers. `Type' is user-oriented, while
* access_ok is kernel-oriented, so the concept of "read" and
* "write" is reversed
*/
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 SCULL_IOCRESET:
	scull_quantum = SCULL_QUANTUM;
	scull_qset = SCULL_QSET;
	break;case SCULL_IOCSQUANTUM: /* Set: arg points to the value */
	if (! capable (CAP_SYS_ADMIN))
		return -EPERM;
	retval = __get_user(scull_quantum, (int __user *)arg);
	break;	case SCULL_IOCTQUANTUM: /* Tell: arg is the value */
	if (! capable (CAP_SYS_ADMIN))
		return -EPERM;
	scull_quantum = arg;
	break;	case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */
	retval = __put_user(scull_quantum, (int __user *)arg);
	break;	case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */
	return scull_quantum;	case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */
	if (! capable (CAP_SYS_ADMIN))
		return -EPERM;
	tmp = scull_quantum;
	retval = __get_user(scull_quantum, (int __user *)arg);
	if (retval == 0)
	retval = __put_user(tmp, (int __user *)arg);
	break;	case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */
	if (! capable (CAP_SYS_ADMIN))
		return -EPERM;
	tmp = scull_quantum;
	scull_quantum = arg;
	return tmp;	case SCULL_IOCSQSET:
	if (! capable (CAP_SYS_ADMIN))
	return -EPERM;
	retval = __get_user(scull_qset, (int __user *)arg);
	break;	case SCULL_IOCTQSET:
	if (! capable (CAP_SYS_ADMIN))
		return -EPERM;
	scull_qset = arg;
	break;	case SCULL_IOCGQSET:
	retval = __put_user(scull_qset, (int __user *)arg);
	break;	case SCULL_IOCQQSET:
	return scull_qset;	case SCULL_IOCXQSET:
	if (! capable (CAP_SYS_ADMIN))
	return -EPERM;
	tmp = scull_qset;
	retval = __get_user(scull_qset, (int __user *)arg);
	if (retval == 0)
	retval = put_user(tmp, (int __user *)arg);
	break;	case SCULL_IOCHQSET:
	if (! capable (CAP_SYS_ADMIN))
	return -EPERM;
	tmp = scull_qset;
	scull_qset = arg;
	return tmp;/** The following two change the buffer size for scullpipe.* The scullpipe device uses this same ioctl method, just to* write less code. Actually, it's the same driver, isn't it?*/	case SCULL_P_IOCTSIZE:
	scull_p_buffer = arg;
	break;	case SCULL_P_IOCQSIZE:
	return scull_p_buffer;	default:  /* redundant, as cmd was checked against MAXNR */
	return -ENOTTY;
	}
	return retval;}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部