ioctl---操作设备的接口

ioctl接口存在的意义:

**********因为对于大部分的驱动来说,除了需要有读写设备的能力,而且还要有通过设备驱动来对硬件进行各种控制的能力.

1.    对于用户空间,ioctl函数的原型是

int ioctl(int fd, unsigned long cmd, ...);
参数说明:

**********fd--------->文件描述符

**********cmd------>控制命令

**********...---------->这三个点不是表示一个变数目的参数,而是单个可选的参数(这是因为有的命令需要参数,ioctl就有三个参数,有的命令不需要参数ioctl就有两个参数).

2.    对于内核空间,ioctl函数的原型------------------>(包含在<linux/fs.h>头文件中)

int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
参数说明:

**********inode对应于用户空间应用程序传递到内核空间的文件描述符fd

**********filp描述文件的结构体

**********cmd对应于用户空间应用程序传递到内核空间的控制命令

**********arg对应于传递到内核控件的命令参数(即三个点)

##############################################################################################################################

对于在内核层的ioctl,为ioctl创建唯一的命令代码

**********命令由四个位段组成,分别是 数据传输方向(dir),设定某一特定驱动命令类型的标志(type),命令序号(nr),参数的大小(size)

**********首先在确定type之前要先查看Documentation/ioctl/ioctl-number.txt文件,不要使用已经使用过的type

**********用于创建命令的宏函数-------->(在头文件<linux/ioctl.h>中)

/* used to create numbers */
#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)					//创建没有参数的命令
#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))		//创建读取设备的命令(get)
#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))		//创建写设备的命令(set)
#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))		//
**********_IOC(dir, type, nr, size)宏函数的定义

#define _IOC(dir,type,nr,size) 	(((dir)  << _IOC_DIRSHIFT) | \		//左移29/30位
	 ((type) << _IOC_TYPESHIFT) | \ 	//左移8位
	 ((nr)   << _IOC_NRSHIFT) | \		//左移0
	 ((size) << _IOC_SIZESHIFT))		//左移16
**********其他宏的定义

# define _IOC_NONE	0U

# define _IOC_WRITE	1U

# define _IOC_READ	2U

#ifdef __KERNEL__
/* provoke compile error for invalid uses of size argument */
extern unsigned int __invalid_size_argument_for_IOC;
#define _IOC_TYPECHECK(t) 	((sizeof(t) == sizeof(t[1]) && 	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? 	  sizeof(t) : __invalid_size_argument_for_IOC)
#else
#define _IOC_TYPECHECK(t) (sizeof(t))
#endif

**********用于在自己实现的驱动里,解析用户空间请求命令的宏函数

/* used to decode ioctl numbers.. */
#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)		//解析参数的大小

**********下面是创建ioctl命令的例子

/*使用字符‘k‘作为驱动命令的类型*/
#define MY_IOC_DRVTYPE  ‘k‘
/*创建一个没有参数,命令号为0的命令*/
#define MY_IOCRESET  _IO(MY_IOC_DRVTYPE, 0)
/*创建一个带有整型参数,命令号为1的命令*/
#define MY_IOCREAD _IOR(MY_IOC_DRVTYPE, 1)
##############################################################################################################################

对于ioctl参数的使用说明

**********当使用一个指针引用用户空间,必须要确保用户空间地址是有效的

**********调用access_ok函数来对地址进行校验.----------------------->(在头文件<asm/uaccess.h>中)

int access_ok(int type, const void *addr, unsigned long size);
参数说明:

**********type是VERIFY_READ或者VERIFY_WRITE,判断是读用户空间还是写用户空间(如是读写给定的地址,使用VERIFY_WRITE,因为VERIFY_WRITE是VERIFY_READ的超级)

#define VERIFY_READ 0
#define VERIFY_WRITE 1
**********addr一个用户空间的地址

**********szie传输数据的大小

**********成功返回1,失败返回0













ioctl---操作设备的接口

上一篇:tomcat虚拟目录和虚拟主机等相关配置


下一篇:第八章 多态