2、应用层系统调用(1)读写 *** 作只是很基础的功能,有的设备需要支持另外的命令去控制;比如串口需要提供设置波特率、数据位、终止位等 *** 作;
(2)如果不同的命令 *** 作,都在write和read中去做判断,对于支持命令比较多的设备,那write和read函数就会很大,不利于维护;
(3)ioctl函数是专门用来处理上层发给驱动程序的命令,设备有需要就去实现,如果没有需要就不实现这个函数,将函数指针赋值为NULL;
#include
/*
* fd:打开设备文件时得到的文件描述符
* cmd:给驱动层传递的命令,这个命令会事先规定号;
* "···":这是C语言的可变参数
*/
int ioctl(int fd, int cmd, ...);
3、驱动层实现ioctl函数接口(1)在linux系统中用man手册可以查询到ioctl函数原型: man 2 ioctl;
struct file_operations
{
······
/*
*file:对应ioctl函数的fd文件描述符
*cmd:对应ioctl函数的cmd命令
*data:对应ioctl函数的可变参数,可以没有值,也可以是指针或者整数值等
*/
long (*unlocked_ioctl) (struct file * file, unsigned int cmd, unsigned long data);
······
}
4、ioctl函数的命令介绍 4.1、命令的格式组成应用层调用的ioctl函数对应到驱动层的unlocked_ioctl函数指针;
4.2、命令的构造(1)设备类型:类型或者叫幻数,表示这是一类设备,可以用一个字符或者8bit表示;
(2)序列号:表示这是设备的第几个命令;
(3)方向:读写方向,这是从应用层的角度来说的,比如"读"表示应用层从设备驱动读数据;
(4)数据尺寸:有的命令是带数据的,这里表明数据的长度;
//传输方向
#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)))
4.3、检查命令和地址的合法性(1)构建命令都是用上面的宏,具体每个字段占多少位其实我们不管关心;
(2)(注意在上面的宏定义中size是传数据的格式,宏定义会自动去计算数据的长度
/* 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)
5、Documentation/ioctl/ioctl-number.txt(1)在驱动的unlocked_ioctl函数实现中,需要对应用层下发的命令进行检查,避免因为应用层发生错误的命令导致程序出问题;
(2)上面宏定义里的nr,是应用层传递下来的命令;
Code Seq#(hex) Include File Comments
========================================================
······
'i' 80-8F linux/i8k.h
'j' 00-3F linux/joystick.h
'k' 00-0F linux/spi/spidev.h conflict!
'k' 00-05 video/kyro.h conflict!
······
ioctl-number.txt文件记录了内核中已经使用的ioctl命令,我们在构建自己的ioctl命令时尽量不要和内核已经使用的命令冲突;
(1)Code:命令中的设备类型字段;
(2)Seq:命令中的序列号字段;
(3)Include File:这些命令被哪个文件占用;
(4)Comments:命令的说明,比如conflict就说明这个命令和其他的文件的定义冲突了;
补充:不同文件中ioctl命令定义冲突并不影响功能,只要在你的驱动程序中命令是唯一的即可(内核自己都有冲突的),但是不建议这么做,尽量不要冲突;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)