这个宏定义 _IOR(MY_MAGIC, 0, int) 是什么意思?

24

我正在查看 ioctl 示例程序,以了解它如何与内核空间通信。该程序使用 WRITE_IOCTL 作为命令。

#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
ioctl(fd, WRITE_IOCTL, "hello world")
我无法理解_IOW(MY_MACIG, 1, int)是什么意思。以下是我下载程序的链接,请帮助我。 http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-4.html

如果您认为我的答案不错,请考虑投票支持它,否则请在评论中提出 :) - Ayman Khamouma
OP链接已损坏。请查看 https://github.com/frobino/de1-soc/blob/master/linux_software/ioctl_kernel/my_device.c 获取代码。 - Jonathan Ben-Avraham
请参考重复问题 https://dev59.com/7mUq5IYBdhLWcg3wSOfS - Jonathan Ben-Avraham
2个回答

18

如您所知,ioctl应该是唯一的,正如在Linux设备驱动程序中所解释的:

  

ioctl命令号应该在整个系统中是唯一的,以防止因向错误的设备发出正确的命令而导致的错误。这样的不匹配很可能发生,并且程序可能会尝试更改非串行端口输入流(例如FIFO或音频设备)的波特率。如果每个ioctl编号都是唯一的,则应用程序会收到EINVAL错误,而不是成功执行某些意外操作。

此外,ioctl可以要求对内核空间进行数据读写。

当一个人创建自己的驱动程序来执行ioctls时,他需要在ioctl命令中描述所有这些内容。

_IO、_IOW、_IOR、_IORW是帮助宏,用于创建唯一的ioctl标识符并添加所需的R/W功能(方向)。

它们可以接受以下参数:魔术数字、命令ID以及将要传递的数据类型(如果有)。

魔术数字是一个唯一的数字,它将允许驱动程序检测到类似于LDD书引用中提到的错误。

命令ID是您的驱动程序理解需要调用哪个命令的一种方式。

最后一个参数(类型)将允许内核了解要复制的大小。

希望这可以帮助。

PS:您可以在Linux设备驱动程序书(第6章)中获得更多详细信息。https://lwn.net/images/pdf/LDD3/ch06.pdf


并不是所有设备都使用主要数字作为魔术数字,只有当它是唯一的时候才可以这样做。请参阅内核文档:http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/Documentation/ioctl/ioctl-number.txt - Ayman Khamouma
1
好的信息。我在查找一些东西时偶然发现了这个。我想补充说,你可以在这里查看这些宏的实现: http://lxr.free-electrons.com/source/include/uapi/asm-generic/ioctl.h。 - Gdogg
1
从技术上讲,我认为这个[ioctl需要是唯一的]是错误的,这只是一个约定,并没有技术上的理由要求ioctl参数必须是唯一的。遵循这个约定可能是个好主意,但并非必须。此外,我怀疑内核是否关心所谓的魔数是哪个设备被调用,因为ioctl的第一个参数就可以做到这一点。 - nyholku
@ Ayman Khamouma感谢您更新您的答案。经过进一步的搜索,我不确定是否有必须遵循的某些约定。因此,尽管我认为我的评论可能是字面上正确的(即参数不需要唯一且不用于查找设备),但仍然可能存在必须遵循某些约定的魔术数字。因此,任何人都应该注意使用用于生成这些魔术数字的宏,以便在需要调用新的魔术数字时遵循约定。 - nyholku

14

来源于http://www.circlemud.org/jelson/software/fusd/docs/node31.html

Linux头文件/usr/include/asm/ioctl.h定义了必须使用的宏来创建ioctl命令编号。这些宏采用三个参数的不同组合:

  • type,一个8位整数,选为特定于设备驱动程序。应选择type,以避免与可能“监听”同一文件描述符的其他驱动程序发生冲突。例如,在内核中,TCP和IP堆栈使用不同的号码,因为发送到套接字文件描述符的ioctl可能被两个堆栈检查。
  • number,一个8位整数命令号。在驱动程序内,应为每个不同类型的ioctl命令选择不同的编号,由驱动程序提供服务。
  • data_type,用于计算客户端和驱动程序之间交换的字节数的类型名称。例如,此参数是结构的名称。

用于生成命令编号的宏有:

  • _IO(int type, int number),用于仅发送类型和编号的简单ioctl,并仅接收一个(整数)返回值。
  • _IOR(int type, int number, data_type),用于从设备驱动程序读取数据的ioctl。驱动程序将被允许向用户返回sizeof(data_type)字节。
  • _IOW(int type, int number, data_type),类似于_IOR,但用于将数据写入驱动程序。
  • _IORW(int type, int number, data_type),_IOR和_IOW的组合。也就是说,客户端会先将数据写入驱动程序,然后再从驱动程序读回数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接