选择哪个函数:select()、poll() 还是 epoll() 来读取 sysfs 属性?

8
我正在处理gpio中断。我有一个在"/sys/class/gpio/gpio38/value"目录下的文件。每当属性value发生变化时,我希望得到通知。那么我该如何在用户空间实现这一点呢?鉴于我已经收集了信息,可以使用select()、poll()或epoll()。对于本应用程序来说,哪种是正确的?还是请您建议我是否可以使用/proc/irq之类的东西。谢谢 :)
2个回答

3
我在这里找到了一些有用的信息 (链接),可能会对你有所帮助:
GPIO信号的路径为/sys/class/gpio/gpio42/(对于GPIO#42),并具有以下读/写属性: "value" …… 读取为0(低电平)或1(高电平)。如果GPIO已配置为输出,则可以写入此值;任何非零值都将被视为高电平。
如果引脚可配置为中断产生中断,并且已配置为生成中断(请参阅“边缘”的说明),则可以在该文件上执行poll(2),并且当触发中断时,poll(2)将返回。如果使用poll(2),请设置事件的POLLPRI和POLLERR。如果使用select(2),请在exceptfds中设置文件描述符。在poll(2)返回之后,要么将lseek(2)移到sysfs文件的开头并读取新值,要么关闭该文件并重新打开该文件以读取该值。
尽管它说是针对“gpio42”,但我想这也适用于您的情况。如果不是,请在我的答案中发表评论。

谢谢@tony-the-lion,这意味着我需要轮询边缘文件还是值文件? - duslabo

1
您可以使用它们中的任何一个。这里的重点是打开GPIO线路值的sysfs文件(例如:/sys/class/gpio/gpio42/value),然后在其上阻塞。
线路状态的变化会被作为异常条件而不是写入来指示(这可能与直觉相反)。
在选择(select)的情况下:
fd_set exceptfds;
int    res;    

FD_ZERO(&exceptfds);
FD_SET(gpioFileDesc, &exceptfds);

res = select(gpioFileDesc+1, 
             NULL,               // readfds - not needed
             NULL,               // writefds - not needed
             &exceptfds,
             NULL);              // timeout (never)

if (res > 0 && FD_ISSET(gpioFileDesc, &exceptfds))
{
     // GPIO line changed
}

1
请注意,并非所有的GPIO都支持中断。如果您正在使用的GPIO不支持中断(这将取决于您使用的确切CPU/SoC),则需要定期读取它。 - user149341
毫无疑问,这种情况是存在的 - 特别是当GPIO线路是通过I2C外设或音频编解码器实现时。然而,在这种情况下,您永远不会在它们上调用select()pselect()poll()epoll()。[poll()及其同类实际上根本不进行轮询] - marko
你好 @Marko,非常感谢您的回复。您能否给我一个您上面提到的选择示例代码?实际上,我的做法是当我执行 echo 1 > file_name 时,通知应该打印出来。这将非常有帮助。 - duslabo
@JeshwanthKumarNK,我不确定你需要的除了上面提到的内容之外还需要什么。我有点困惑为什么你在上面的评论中谈论写入值文件,却又问如何使用select()来检测行的变化。 - marko

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