【问题标题】:Embedded Linux poll() returns constantly嵌入式 Linux poll() 不断返回
【发布时间】:2013-04-20 09:20:14
【问题描述】:

我有一个特殊的问题。当我知道没有什么可读的时候,民意调查不断返回。

所以设置如下,我有 2 个文件描述符,它们构成轮询监视的 fd 集的一部分。一种是用于引脚从高到低的变化 (GPIO)。另一个用于代理输入。代理输入出现问题。

处理顺序为:启动主函数;然后它将轮询;将数据写入代理;民意调查将中断;接受数据;通过 SPI 发送数据;通过将 GPIO 拉低来接收从设备,想要发送 ack 的信号; Poll() 感知到这种下降并做出反应; 无限的 POLLIN :(

如果 Poll 功能没有超时,程序运行良好。我在投票中包含超时的那一刻。民意调查不断返回。不知道我在这里做错了什么。

     while(1)
         {
            memset((void*)fdset, 0, sizeof(fdset));
            fdset[0].fd = gpio_fd;
            fdset[0].events = POLLPRI; // POLLPRI - There is urgent data to read 

            fdset[1].fd = proxy_rx;
            fdset[1].events = POLLIN; // POLLIN   - There is data to read
            rc = poll(fdset, nfds, 1000);//POLL_TIMEOUT);

            if (rc < 0)     // Error
            {
                    printf("\npoll() failed/Interrupted!\n");
            }
            else if (rc == 0)       // Timeout occurred
            {
                  printf(" poll() timeout\n");
            }

            else {
                   if (fdset[1].revents & POLLIN)
                   {
                     printf("fdset[1].revents & POLLIN\n");
                    if( (resultR =read(fdset[1].fd,command_buf,10)<0) {                                   
                                    printf("Failed to read Data\n");

                            }
                    if (fdset[0].revents & POLLPRI)
                            //if( (gpio_fd != -1) && (FD_ISSET(gpio_fd, &err)))
                    {
                         lseek(fdset[0].fd, 0, SEEK_SET); // Read from the start of the file
                            len = read(fdset[0].fd, reader, 64);


                     }

这就是我的代码的要点,抱歉不整洁,这个界面有点习惯了。

我也使用过 GDB,在调试时,我发现 GPIO 描述符设置为 revents = 0x10,这意味着发生了错误并且也发生了 POLPRI。

poll(2) doesn't empty the event queue 在上面的链接中解决了类似的问题。但是当我得到 POLLIN 时,我确实一直在阅读。令人惊讶的是,这个问题仅在我包含超时时才会出现,如果我将轮询超时替换为 -1,它会完美运行。

请帮忙。

【问题讨论】:

  • 虽然我不认为这是导致此特定问题的原因,但请注意,GPIO 的sysfs 接口仅在poll()select() 中有线程阻塞时检测边缘- 在下一次调用之前它不会缓冲它们。除非您绝对确定(通过协议设计和实现)当 ACK 出现时您将始终被阻止,否则可能会出现竞争条件并进入您永远不会收到另一个状态的状态。我的解决方案与您的方案类似,是内核模式驱动程序。
  • 自从我第一次发布这篇文章已经七年了。哇。我们确实重构了这段代码使其更简单。最终导致这种情况的主要原因是连接设备的驱动程序问题,他们无法清除标志。正如上面 Marko 所指出的那样,没有缓冲区,因此引入了一些可能会遗漏的边缘情况(后来也遇到了这个问题)

标签: linux embedded-linux


【解决方案1】:

poll 失败(返回-1)时,你应该对errno 做一些事情,也许是通过perror;并且您的nfdspoll 的第二个参数)没有设置,但它应该是常量 2。

可能 GCC 编译器会发出警告,至少在启用所有警告 (-Wall) 的情况下,关于 nfds 未设置。

(我猜nfds 未初始化可能是一些“随机”的大值......所以内核可能正在轮询其他“随机”文件描述符,那些在你的fdset 之后的索引2...)

顺便说一句,你可以strace 你的程序。而且使用fdset这个名字有点混乱(可以参考select(2))。

【讨论】:

  • poll() 没有失败,但是我确实使用了 perror 想法并打印出弹出的错误(我一直在接收:GPIO 文件描述符的设备或资源忙)。 nfds 最初在 main 中设置为 2,不包括该部分,抱歉。此外,我看到它在我允许其他设备更改 GPIO 时立即发生。还是很困惑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
相关资源
最近更新 更多