首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用``poll()‘检查阻塞

用``poll()‘检查阻塞
EN

Stack Overflow用户
提问于 2021-07-14 13:56:41
回答 1查看 323关注 0票数 0

我想检查文件描述符是否会阻塞某个事件,并且我有了使用poll()和0超时的想法:

代码语言:javascript
复制
int wouldblock(int fd, short event)
{
  struct pollfd pfd;
  pfd.fd = fd;
  pfd.events = event;
  return (poll(&pfd,1,0) == 0);
}

...
  if (wouldblock(0,POLLIN)) ...
...

或者流是可用的,轮询()应该返回1,或者它会阻塞,超时将启动返回0。(让我们暂时搁置错误检查)。

它可以工作(至少“它在我的机器上工作”),但我想知道我是否错过了什么?也许poll()太过分了,而我对系统的压力太大了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-14 14:56:02

我想知道我是不是错过了什么?

poll可以立即返回,而且操作仍然可以阻止。这可能发生,因为从poll()返回和启动操作之间还有时间。当一个事件改变了连接到文件描述符的事物的状态,而该事件发生在您的进程从poll()返回并即将启动操作时,就会发生这种情况。

最常见的情况是,两个进程同时从一个管道中返回poll()ing和read()ing --这可能发生两个poll都返回,但只有一个read获胜。

代码语言:javascript
复制
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <poll.h>
#include <sys/wait.h>
int main(void)
{
    system("mkfifo /tmp/fifo ; echo > /tmp/fifo & sleep 0.1");
    fork();
    int fd = open("/tmp/fifo", O_RDWR);
    sleep(1);
    printf("poll=%d\n", (int)poll(&(struct pollfd){fd, POLLIN}, 1, 0));
    sleep(1);
    printf("read=%d\n", (int)read(fd, (char[1]){}, 1));
    printf("%d exiting!\n", (int)getppid());
    wait(0);
}

有足够运气的产出:

代码语言:javascript
复制
poll=1
poll=1
read=1
136769 exiting!

而另一个fork()ed进程正在等待read

我还记得在内核邮件列表中也看到了一个线程,它的功能是丢弃旧的网络数据包以防止阻塞。有了这样一个特性,程序就可以:poll()在网络套接字上,然后内核决定丢弃数据包,然后进程执行read()只会发现数据包不再存在。

使用poll()作为“通知”系统-- poll()返回文件描述符,您应该“检查”它们是否有可读取的内容。然后,您应该检查“是否真实”,如果有什么东西可以通过调用read()阅读。

在实际的应用程序中,我将移动"wouldblock“函数上一层,而不是检查文件描述符是否会阻塞,而是检查是否收到了我所使用的任何协议中的完整逻辑包。将其称为has_received_a_packet,它将使用read()接收数据,并在缓冲区中进行累积,并检查是否接收到完整的数据包。

也许民意测验太过分了,而我对系统的压力太大了?

我想是的,你可以直接打电话给read,当场就能接收到这些数据。类似于ungetc的实现方式:

代码语言:javascript
复制
struct buf {
   char data;
   bool hasit;
};
int readbuf_has_something(struct buf *readbuf, int fd) {
    if (!readbuf->hasit) {
        set_nonblock(fd);
        ssize_t r = read(fd, &readbuf->data, 1);
        if (r == 1) readbuf->hasit = 1;
        if (ret < 0) return -EIO;
    }
    return readbuf->hasit;
}
int readbuf_something(struct buf *readbuf, int fd) {
    if (readbuf->hasit) {
      readbuf->hasit = 0;
      return readbuf.data;
    }
    set_block(fd);
    ssize_t r = read(fd, &readbuf->data, 1);
    if (r == 1) return readbuf->data;
    return EOF;
}

这样的实现将减少一个上下文更改,而不是使用poll,然后是read --只要读取数据,它们就在那里了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68379482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档