ioctl接口

一、定义

ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。
简言之就是对设备的一些特性进行管理,例如传感器的数据采集频率、串口波特率、停止位等等。

  • 通常来说,使用read write接口,来读写数据;使用ioctl接口设置一些属性等等。
  • ioctl接口既可以读,也可以写,但是读写大数据的效率不如使用read write接口高。

需要注意的是:新内核中file_operations 结构体对ioctl接口的定义发生了变化, :

原先的, 参见include/linux/fs.h, version 2.6.17, line 1015

int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);

被改为了, 参见include/linux/fs.h, version 4.11, line 1654,

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

ref:

内核新的ioctl方式--unlocked_ioctl和compat_ioctl(解决error:unknown field 'ioctl' specified in initializer)_CHENG Jian的博客-CSDN博客

二、命令格式

在linux中,提供了一种 ioctl 命令的统一格式,将 32 位 int 型数据划分为四个位段,如下图所示:

 内核的 /include/uapi/asm-generic/ioctl.h 头文件,定义了 ioctl 函数的相关宏

/* 合成宏 */
#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)))
/*
_IO:       定义没有数据传递的 ioctl 命令
_IOW:      定义向驱动中写入数据的 ioctl 命令(copy_from_user)
_IOR:      定义从驱动中读数据的ioctl命令(copy_to_user)
_IOWR:     定义带读写参数的 ioctl 命令,先写后读的这类命令
*/

/* 反向解析 ioctl 宏接口 */
#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)

三、代码示例

和open read write函数同理,当在应用层代码中调用ioctl接口的时候,其实调用的内核file_operations的unlocked_ioctl结构体成员。

用户空间:

#include <sys/ioctl.h> 
int ioctl(int fd, int cmd, ...) ;

输入参数:

  • 参数1:设备描述符
  • 参数2:指令,如某一个命令对应驱动层的某一个功能
  • 参数3:可变参数,跟命令有关,传递进入驱动层的参数或者是接收数据的缓存

返回值:

  • 成功:返回 0
  • 失败:返回 -1,并设置全局变量 errorno 值

代码示例:


/* 定义命令 */
#define MYCMD _IO('c', 0)

int ret;
ret = ioctl(fd, MYCMD);
if (ret == -1) {
    printf("ioctl: %s\n", strerror(errno));
}


 

内核空间:

#include <linux/ioctl.h>	/* 内核空间 */
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  • 参数1:文件结构体指针
  • 参数2:指令(对应应用层ioctl函数的第二个参数)
  • 参数3:应用层传递给驱动层的数据或者是接收数据用到的缓存地址

ref:

Python成神之路 - linux ioctl函数介绍

设备驱动与 ioctl 函数详细分析_MagicSong-程序员宝宝_ioctl函数 - 程序员宝宝

ioctl - 刘强民的博客 | cslqm Blog

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值