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:
<span style="white-space:pre">	</span>scull_quantum = SCULL_QUANTUM;
<span style="white-space:pre">	</span>scull_qset = SCULL_QSET;
<span style="white-space:pre">	</span>break;
       
 case SCULL_IOCSQUANTUM: /* Set: arg points to the value */
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">		</span>return -EPERM;
<span style="white-space:pre">	</span>retval = __get_user(scull_quantum, (int __user *)arg);
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCTQUANTUM: /* Tell: arg is the value */
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">		</span>return -EPERM;
<span style="white-space:pre">	</span>scull_quantum = arg;
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */
<span style="white-space:pre">	</span>retval = __put_user(scull_quantum, (int __user *)arg);
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */
<span style="white-space:pre">	</span>return scull_quantum;

 <span style="white-space:pre">	</span>case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">		</span>return -EPERM;
<span style="white-space:pre">	</span>tmp = scull_quantum;
<span style="white-space:pre">	</span>retval = __get_user(scull_quantum, (int __user *)arg);
<span style="white-space:pre">	</span>if (retval == 0)
<span style="white-space:pre">	</span>retval = __put_user(tmp, (int __user *)arg);
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">		</span>return -EPERM;
<span style="white-space:pre">	</span>tmp = scull_quantum;
<span style="white-space:pre">	</span>scull_quantum = arg;
<span style="white-space:pre">	</span>return tmp;
        
 <span style="white-space:pre">	</span>case SCULL_IOCSQSET:
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">	</span>return -EPERM;
<span style="white-space:pre">	</span>retval = __get_user(scull_qset, (int __user *)arg);
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCTQSET:
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">		</span>return -EPERM;
<span style="white-space:pre">	</span>scull_qset = arg;
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCGQSET:
<span style="white-space:pre">	</span>retval = __put_user(scull_qset, (int __user *)arg);
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_IOCQQSET:
<span style="white-space:pre">	</span>return scull_qset;

 <span style="white-space:pre">	</span>case SCULL_IOCXQSET:
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">	</span>return -EPERM;
<span style="white-space:pre">	</span>tmp = scull_qset;
<span style="white-space:pre">	</span>retval = __get_user(scull_qset, (int __user *)arg);
<span style="white-space:pre">	</span>if (retval == 0)
<span style="white-space:pre">	</span>retval = put_user(tmp, (int __user *)arg);
<span style="white-space:pre">	</span>break;


 <span style="white-space:pre">	</span>case SCULL_IOCHQSET:
<span style="white-space:pre">	</span>if (! capable (CAP_SYS_ADMIN))
<span style="white-space:pre">	</span>return -EPERM;
<span style="white-space:pre">	</span>tmp = scull_qset;
<span style="white-space:pre">	</span>scull_qset = arg;
<span style="white-space:pre">	</span>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?
         */

 <span style="white-space:pre">	</span>case SCULL_P_IOCTSIZE:
<span style="white-space:pre">	</span>scull_p_buffer = arg;
<span style="white-space:pre">	</span>break;

 <span style="white-space:pre">	</span>case SCULL_P_IOCQSIZE:
<span style="white-space:pre">	</span>return scull_p_buffer;

 <span style="white-space:pre">	</span>default:  /* redundant, as cmd was checked against MAXNR */
<span style="white-space:pre">	</span>return -ENOTTY;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return retval;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

john_liqinghan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值