linux下ioctl小结

cmd由一个int型整数组成

方向/DIR大小/SIZE幻数/TYPE序数/NR
30-3130-1615-87-0
#define _IOC(dir,type,nr,size) \
	(((dir)  << _IOC_DIRSHIFT) | \
	 ((type) << _IOC_TYPESHIFT) | \
	 ((nr)   << _IOC_NRSHIFT) | \
	 ((size) << _IOC_SIZESHIFT))

部分幻数,内核已使用Documentation/userspace-api/ioctl/ioctl-number.rst,可定义没使用的

以下面的例子来看下

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include<linux/slab.h>

/*
from include/uapi/asm-generic/ioctl.h
#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)

#define _IOC_NRSHIFT	0
#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)

#ifndef _IOC_NONE
# define _IOC_NONE	0U
#endif

#ifndef _IOC_WRITE
# define _IOC_WRITE	1U
#endif

#ifndef _IOC_READ
# define _IOC_READ	2U
#endif

#define _IOC(dir,type,nr,size) \
	(((dir)  << _IOC_DIRSHIFT) | \
	 ((type) << _IOC_TYPESHIFT) | \
	 ((nr)   << _IOC_NRSHIFT) | \
	 ((size) << _IOC_SIZESHIFT))

#ifndef __KERNEL__
#define _IOC_TYPECHECK(t) (sizeof(t))
#endif

#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))

#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
*/

#define	SET_TX_CARRIER			_IOW(0xf5,0x80, int)

int test_open(struct inode *node, struct file *filp)
{
	return 0;
}

int test_close(struct inode *node, struct file *filp)
{
	return 0;
}

static long test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int freq;
	switch (cmd) {
	case SET_TX_CARRIER:
		if (get_user(freq, (unsigned int __user *)arg)) {
			return -EFAULT;
		}
		break;
	default:
		return -ENOIOCTLCMD;
	}
	return 0;
}

struct file_operations test_fops = {
	.open = test_open,
	.unlocked_ioctl = test_ioctl,
	.release = test_close,
};

static struct miscdevice test_dev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "test",
	.fops = &test_fops,
};

static int __init test_init(void)
{
	int ret;
	printk("test_init\n");
	ret = misc_register(&test_dev);
	if (ret != 0) {
		pr_err("cannot register miscdev\n");
	}

	printk("_IOC_NRSHIFT=%d,_IOC_NRMASK=0x%x\n", _IOC_NRSHIFT,
	       _IOC_NRMASK << _IOC_NRSHIFT);
	printk("_IOC_TYPESHIFT=%d _IOC_TYPEMASK0x%x\n", _IOC_TYPESHIFT,
	       _IOC_TYPEMASK << _IOC_TYPESHIFT);
	printk("_IOC_SIZESHIFT=%d _IOC_SIZEMASK=0x%x\n", _IOC_SIZESHIFT,
	       _IOC_SIZEMASK << _IOC_SIZESHIFT);
	printk("_IOC_DIRSHIFT=%d _IOC_DIRMASK=0x%x\n", _IOC_DIRSHIFT,
	       _IOC_DIRMASK << _IOC_DIRSHIFT);

	pr_info("SET_TX_CARRIER=0x%lx\n", SET_TX_CARRIER);
	pr_info("_IOC_DIR=%ld\n", _IOC_DIR(SET_TX_CARRIER));
	pr_info("_IOC_SIZE=%ld\n", _IOC_SIZE(SET_TX_CARRIER));
	pr_info("_IOC_TYPE=0x%lx\n", _IOC_TYPE(SET_TX_CARRIER));
	pr_info("_IOC_NR=0x%lx\n", _IOC_NR(SET_TX_CARRIER));
	return 0;
}

static void __exit test_exit(void)
{
	printk("test_exit\n");
	misc_deregister(&test_dev);
}

module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL v2");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值