05-字符设备驱动之ioctl

04-最简单的字符设备驱动这篇文章中介绍了一个简单的字符设备驱动,包含了4个基本系统调用:openclosereadwrite。其中readwrite可以在应用空间和内核空间交换数据。但是某些操作不太适合他们来实现。比如:

  • 清空kBuf
  • 设置kBuf的操作行为
  • 读取kBuf的属性,比如里面有多少有效数据等等。

这些操作不是"读数据"或"写数据",而是"控制设备"。此时我们就需要另一个系统调用,ioctl来实现"控制设备"。

ioctl 的作用

ioctl = I/O Control(输入/输出控制)

read/write     →  数据传输(data transfer),同一类数据。
ioctl          →  设备控制(device control),可以传输各种不同的数据,相关参数可以起到解析数据的提示作用。

用户空间的 ioctl 调用

#include <sys/ioctl.h>

int ioctl(int fd, unsigned long cmd, ...);

参数:

  • fd:文件描述符(open() 返回的)
  • cmd:命令编号(你自己定义)
  • ...:可选参数(根据命令不同)

ioctl参数cmd的定义

ioctl的参数cmd是一个 32位整数,包含多个字段:

  31        30  29    16 15      8 7       0
  ┌───────────┬─────────┬─────────┬─────────┐
  │    dir    │   size  │   type  │   nr    │
  └───────────┴─────────┴─────────┴─────────┘
    方向             数据大小     魔数      编号
    (2位)            (14位)     (8位)     (8位)

字段说明:

  • nr (number):命令编号(0-255)
  • type:魔数(幻数),标识你的驱动,防止将别的驱动定义的ioctl命令用于操作此驱动,避免混淆,比如A驱动定义了一个用于复位的命令:A_CMD_RESET, B驱动定义了一个用于清空缓存区的命令:B_CMD_CLEAN,假设它们除了type不同,其他都一样,万一不小心把B_CMD_CLEAN用到A驱动上,你会觉得很差异,因为从宏的字面意思来看,你认为你在做清空缓存操作,结果设备无任何反应。
  • size:传输数据的大小
  • dir(direction):数据方向
    • _IOC_NONE:无数据传输
    • _IOC_READ:从驱动读取数据到用户空间
    • _IOC_WRITE:从用户空间写入数据到驱动
    • _IOC_READ|_IOC_WRITE:双向
posted @ 2025-10-11 17:49  thammer  阅读(5)  评论(0)    收藏  举报