我有一个fd描述符,我可以通过调用read(fd, buffer,...)
来读取它。现在,我想在实际拨打电话之前检查是否有任何内容需要阅读,因为呼叫是阻塞的。我该怎么做?
答案 0 :(得分:54)
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
上面的代码片段将为非阻塞访问配置此类描述符。如果在调用read时数据不可用,则系统调用将失败,返回值为-1,并且errno设置为EAGAIN。有关详细信息,请参阅fnctl手册页。
或者,您可以使用select和可配置的超时来检查和/或等待指定的时间间隔以获取更多数据。这种方法可能就是你想要的,效率更高。
答案 1 :(得分:12)
使用select
或poll
来查询文件描述符是否有可供读取的数据:
fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
答案 2 :(得分:6)
好的,STDIN
可以按照您的意愿在非阻塞模式下读取。您首先需要将套接字设置为非阻塞模式,如
int flags = fcntl(fd, F_GETFL, 0);
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK))
;// some kind of fail
当您准备好从缓冲区读取数据时,您可以按如下方式尝试读取:
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.
}
请注意,1024
的缓冲区大小当然是任意的。
答案 3 :(得分:3)
我认为您应该使用select
或poll
函数来检查是否有从描述符中读取的内容。
答案 4 :(得分:1)
根据您正在做的事情,您可以将问题彻底解决,并使用select
告诉您文件描述符何时可以阅读。
答案 5 :(得分:1)
查看您用于特定编程目的的API或系统/工具。 (描述符/文件描述符在Linux编程中有很多用途,如套接字编程,文件操作,shared_memory等)。
例如,有一次我使用了inotify(用于监视文件系统事件)。此API使您能够从第一点创建非阻塞文件,并且无需使用fcntl或此类API来修改创建的文件描述符。
您可能会使用的其他工具或API具有此类功能,您可以在启动或此类步骤中设置此类选项(请先检查)。
但通常是使用fcntl是答案,知道inotify本身也使用fcntl本身可能会很有趣。 (参考Linux的手册页)
select()可以为您提供与在文件描述符上操作相同的功能,用于监视具有指定限制时间的事件,但请记住,select的主要用途是用于监视多个文件描述符。
答案 6 :(得分:1)
use poll for timeout:
struct pollfd p;
int n;
while ((n = poll(&p, 1, iTo)) < 0)
{
if (errno == EAGAIN || errno == EINTR)
continue;
}
if (!n) {
errno = ETIMEDOUT;
}
while ((len = read(Fd, anyBuff, sizeof(anyenter code hereBuff))) < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
}