我正在围绕 libgpiod 的接口编写一些代码。比如我想设置一条线输出高电平。在引擎盖下,libgpiod 打开内核为该行提供的 fd,然后调用ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, ...)
.
我的问题是:
这个特定的
ioctl()
调用(带有GPIO_V2...
参数)理论上(可能)是否以与写作可以是任意文件描述符吗?ioctl()
理论上来说,呼叫通常会阻塞吗?例如,首先请求线路还涉及ioctl()
芯片的 on a fd。 I2C 怎么样ioctl()
?fd
如果它是阻塞的,那么行 struct ( ) 中的底层是否是line->fd_handle->fd
我需要在事件循环中等待的底层(例如,epoll()
或像 libuv 这样的抽象事件库)?
我试图通过研究来回答这个问题,但是(a)搜索“ioctl”和“blocking”的任何组合只会给出以下结果:环境a fd 是否阻塞,并且 (b) 它不在我能找到的手册页或内核文档中。
答案1
GPIO_V2_LINE_SET_VALUES_IOCTL
看起来足够安全;它符合预期的用途ioctl
,“操纵特殊文件的底层设备参数”。它的实施于linereq_set_values
,它获取锁,但我不认为锁可以无限期地阻塞(它的用户都是非阻塞的)。理论上,人们可能期望
ioctl
s 是非阻塞的,因为它们主要用于配置驱动程序。然而,有些ioctl
s 的作用远不止于此:例如,FICLONERANGE
和FICLONE
涉及实际的 I/O,更糟糕的是,它们受到某些网络文件系统(例如 NFS v4.2)的支持,因此可以想象它们会无限期地阻塞。参见上面第 1 点。
答案2
首先,GPIO uAPIioctl()
是同步的,即在操作完成之前它们不会返回。它们不是异步的,因此您可以启动操作并等待完成通知。
因此,针对您的第三个问题,没有 fd 等待 GPIO uAPI完成 - 调用线程在操作完成之前ioctl()
不会返回。ioctl()
(uAPI中fds的可读性与s无关ioctl()
,但表示发生了异步事件,可以从文件中读取事件详细信息。对于线路请求fds来说是边缘事件。对于芯片fds来说是对线路请求状态的更改 - 是否已请求、释放或重新配置。)
我对您的第一个问题的最初反应是 GPIO uAPI ioctl()
,例如 GPIO_V2_LINE_SET_VALUES_IOCTL
,实际上是非阻塞的。虽然它们可能涉及覆盖共享状态的互斥锁,但最终它们会保护对控制硬件的寄存器的写入,并且这些写入几乎会立即返回,因此任何争用都将转瞬即逝,并且任何开销都将小于用户空间中线程之间的上下文切换。鉴于此,您也可以直接调用它 - 即使在循环内也是如此epoll()
。
对于直接托管在 SOC 和微控制器上的 GPIO,这可能是正确的,但是对于通过 I2C、SPI 或其他方式连接的 GPIO 扩展器芯片,ioctl()
在相应的事务完成之前不会返回。需要多长时间取决于总线等,并且延迟对您来说是否重要取决于您的应用程序。它不会无限期地阻止您的事件循环,但它可能会比您希望的时间更长。
因此,回答你的第一个问题,如果你的意思是无限期地阻止,那么不,他们不应该无限期地阻止。但在某些情况下它们可能需要相当长的时间才能完成,这对您来说可能很重要。
我认为这也适用于第二个问题。一般来说,它们可以被认为是非阻塞的,但这取决于具体情况ioctl()
和您的应用程序。