字符设备ioctl接口详解

Posted 正在起飞的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符设备ioctl接口详解相关的知识,希望对你有一定的参考价值。

1、为什么要引入ioctl接口?

(1)读写操作只是很基础的功能,有的设备需要支持另外的命令去控制;比如串口需要提供设置波特率、数据位、终止位等操作;
(2)如果不同的命令操作,都在write和read中去做判断,对于支持命令比较多的设备,那write和read函数就会很大,不利于维护;
(3)ioctl函数是专门用来处理上层发给驱动程序的命令,设备有需要就去实现,如果没有需要就不实现这个函数,将函数指针赋值为NULL;

2、应用层系统调用

#include <sys/ioctl.h>

/*
*	fd:打开设备文件时得到的文件描述符
*	cmd:给驱动层传递的命令,这个命令会事先规定号;
*	"···":这是C语言的可变参数
*/
int ioctl(int fd, int cmd, ...);

(1)在linux系统中用man手册可以查询到ioctl函数原型: man 2 ioctl;

3、驱动层实现ioctl函数接口

struct file_operations

	······
	/*
	*file:对应ioctl函数的fd文件描述符
	*cmd:对应ioctl函数的cmd命令
	*data:对应ioctl函数的可变参数,可以没有值,也可以是指针或者整数值等
	*/
	long (*unlocked_ioctl) (struct file * file, unsigned int cmd, unsigned long data);
	······

应用层调用的ioctl函数对应到驱动层的unlocked_ioctl函数指针;

4、ioctl函数的命令介绍

4.1、命令的格式组成

(1)设备类型:类型或者叫幻数,表示这是一类设备,可以用一个字符或者8bit表示;
(2)序列号:表示这是设备的第几个命令;
(3)方向:读写方向,这是从应用层的角度来说的,比如"读"表示应用层从设备驱动读数据;
(4)数据尺寸:有的命令是带数据的,这里表明数据的长度;

4.2、命令的构造

//传输方向
#define _IOC_NONE		0U 	//无数据传输
#define _IOC_WRITE		1U	//向驱动中写数据
#define _IOC_READ		2U	//从驱动中读数据
_IOC_READ	 | _IOC_WRITE		//双向传送

/*
*type:设备类型
*nr:序列号
*size:这里传数据的格式,宏定义会自动去计算数据的长度
*/
//没有数据传递的命令
#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)))

(1)构建命令都是用上面的宏,具体每个字段占多少位其实我们不管关心;
(2)(注意在上面的宏定义中size是传数据的格式,宏定义会自动去计算数据的长度

4.3、检查命令和地址的合法性

/* 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)

(1)在驱动的unlocked_ioctl函数实现中,需要对应用层下发的命令进行检查,避免因为应用层发生错误的命令导致程序出问题;
(2)上面宏定义里的nr,是应用层传递下来的命令;

以上是关于字符设备ioctl接口详解的主要内容,如果未能解决你的问题,请参考以下文章

Linux下的ioctl()函数详解

Linux字符设备-内核态数据与用户态数据互传

Linux——Linux驱动之使用ioctl接口进行设备参数设置应用实践(ioctl接口命令规则代码实现)

文件IO详解(十七)---ioctl函数详解

07 字符设备

帧缓冲字符设备接口