读取描述符的非阻塞调用

Sma*_*ess 36 c unix

我有一个fd描述符,我可以通过调用来读取它read(fd, buffer,...).现在,我想在实际拨打电话之前检查是否有任何内容需要阅读,因为呼叫是阻塞的.我该怎么做呢?

Jud*_*den 56

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
Run Code Online (Sandbox Code Playgroud)

上面的代码片段将为非阻塞访问配置这样的描述符.如果在调用read时数据不可用,则系统调用将失败,返回值为-1,并且errno设置为EAGAIN.有关更多信息,请参见fnctl手册页.

或者,您可以使用带有可配置超时的select来检查和/或等待指定的时间间隔以获取更多数据.这种方法可能就是你想要的,效率更高.

  • 这不是正确的答案.针对常规fs的O_NONBLOCK没有效果(read()将保持阻塞)并且select()将始终错误地将fd报告为"就绪".对于Linux上的常规文件,可靠的非阻塞IO基本上(并且不幸地)不受支持. (5认同)
  • [一些](http://www.linux-mag.com/id/308/) [good](https://www.remlab.net/op/nonblock.shtml) [来源](http://neugierig) .org/software/blog/2011/12/nonblocking-disk-io.html) 在常规文件和非阻塞 I/O 上。但是,如果`fd` 是stdin,那么在从终端/管道读取时让`O_NONBLOCK` 加快速度而从文件读取时什么都不做似乎是无害的。 (2认同)

R..*_*R.. 12

使用selectpoll查询文件描述符是否具有可读取的数据:

fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
Run Code Online (Sandbox Code Playgroud)

  • 可能吧,但无论如何,“select”都是一个可怕的想法,因为如果“fd>=FD_SETSIZE”,“FD_SET”就会调用 UB。只需使用“民意调查”即可。 (3认同)
  • 是不是FD_SET(fd,&fds);`呢? (2认同)
  • `poll()`现在在POSIX中标准化,因此它总是可以用来代替`select()`.http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html (2认同)

Ken*_*kot 7

好的,STDIN可以按照您的意愿在非阻塞模式下阅读.您首先需要将套接字设置为非阻塞模式,如

int flags = fcntl(fd, F_GETFL, 0);
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    ;// some kind of fail
Run Code Online (Sandbox Code Playgroud)

当您准备从缓冲区读取数据时,可以尝试如下读取:

int count;
char buffer[1024];
count = read(fd, buffer, 1024);
if(count < 0 && errno == EAGAIN) {
    // If this condition passes, there is no data to be read
}
else if(count >= 0) {
    // Otherwise, you're good to go and buffer should contain "count" bytes.
}
else {
    // Some other error occurred during read.
}
Run Code Online (Sandbox Code Playgroud)

请注意,缓冲区大小当然1024是任意的.

  • 第二个文本不是(count&gt; 0),不是(count&gt; = 0)吗?根据我的阅读,返回零表示EOF。如果通道仍处于打开状态,但是没有数据,则返回-1,并且errno设置为EAGAIN。对? (2认同)