linux - IOCTL Linux 设备驱动程序

谁能解释一下,

  1. 什么是IOCTL
  2. 它是做什么用的?
  3. 如何使用它?
  4. 为什么我不能定义与 IOCTL 功能相同的新函数?

最佳答案

ioctl 函数对于实现设备驱动程序以在设备上设置配置很有用。例如具有配置选项以检查和设置字体系列、字体大小等的打印机。ioctl 可用于获取当前字体以及将字体设置为新字体。用户应用程序使用 ioctl 向打印机发送代码,告诉它返回当前字体或将字体设置为新字体。

int ioctl(int fd, int request, ...)
  1. fd为文件描述符,open返回的;
  2. request 是请求代码。例如 GETFONT 将从打印机获取当前字体,SETFONT 将设置打印机上的字体;
  3. 第三个参数是void *。根据第二个参数,第三个可能存在也可能不存在, 例如如果第二个参数是SETFONT,第三个参数可以是字体名称如"Arial";

int request 不仅仅是一个宏。用户应用程序需要生成请求代码和设备驱动程序模块来确定必须使用设备上的哪个配置。应用程序使用 ioctl 发送请求代码,然后使用设备驱动程序模块中的请求代码来确定要执行的操作。

一个请求代码有 4 个主要部分

    1. A Magic number - 8 bits
    2. A sequence number - 8 bits
    3. Argument type (typically 14 bits), if any.
    4. Direction of data transfer (2 bits).  

如果请求代码是SETFONT在打印机上设置字体,数据传输的方向将是从用户应用程序到设备驱动程序模块(用户应用程序发送字体名称“Arial " 到打印机)。 如果请求代码是GETFONT,方向是从打印机到用户应用程序。

为了生成请求代码,Linux 提供了一些预定义的类似函数的宏。

1._IO(MAGIC, SEQ_NO) 都是 8 位,0 到 255,例如假设我们要暂停打印机。 这不需要数据传输。所以我们会生成如下的请求代码

#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

现在使用 ioctl 作为

ret_val = ioctl(fd, PAUSE_PRIN);

驱动模块中相应的系统调用会接收到代码并暂停打印机。

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGICSEQ_NO 同上,TYPE给出下一个参数的类型,回想 ioctl 的第三个参数是 void *__IOW 中的 W 表示数据流是从用户应用程序到驱动模块。举个例子, 假设我们要将打印机字体设置为 "Arial"
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

进一步,

char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font); 

现在 font 是一个指针,这意味着它是一个最好表示为 unsigned long 的地址,因此 _IOW 的第三部分提到了类型像这样。此外,这个字体地址作为 unsigned long 传递给在设备驱动模块中实现的相应系统调用,我们需要在使用它之前将其转换为正确的类型。内核空间可以访问用户空间,因此这是可行的。另外两个类似函数的宏是 __IOR(MAGIC, SEQ_NO, TYPE)__IORW(MAGIC, SEQ_NO, TYPE),其中数据流将从内核空间流向用户空间和两种方式。

如果这有帮助,请告诉我!

https://stackoverflow.com/questions/15807846/

相关文章:

python - Django:登录后重定向到上一页

python - Python中的SFTP? (平台无关)

linux - Bash循环中的计数器增量不起作用

linux - 如何从命令行在 GNOME 终端中打开一个新选项卡?

linux - 如何提取 filename.tar.gz 文件

python - 如何在 Python 请求中禁用安全证书检查

python - 如何从 Visual Studio Code 中执行 Python 代码

linux - 仅在尚未运行时运行 cron 作业

linux - 检查 Bash 列表中是否存在变量

python - 在 Python : x**. 5 或 math.sqrt(x) 中哪个更快?