如何检查stdin是否仍然没有阻塞打开?

时间:2009-10-20 12:27:43

标签: c stream stdin nonblocking

我需要用纯C编写的程序在stdin关闭时停止执行。

在程序主循环中有无限期的工作,我无法在那里使用阻塞检查(如getc())(没有数据应该在stdin上到达 - 它只是在未知时间内保持打开状态)

我打算在实现inetd,xinetd或其类似物中托管的网络守护程序时使用所描述的功能 - 它应该在连接保持打开时在stdout上发出数据,并在关闭时正确完成工作。现在我的程序被托管服务杀死,因为它在连接终止后不会停止。

我想知道将fctntl() O_NONBLOCK标志应用于stdin描述符是否允许我在非阻塞模式下使用read()函数?我应该以某种方式使用select()吗?

P.S。数据不是假定的,但可能会到达stdin。一种非阻塞读出方式可以解决这个问题。

5 个答案:

答案 0 :(得分:7)

select()完全符合您的要求:表示文件描述符(文件,套接字等)上的操作(在本例中为read)不会阻塞。

#include <stdio.h>
#include <sys/select.h>

int is_ready(int fd) {
    fd_set fdset;
    struct timeval timeout;
    int ret;
    FD_ZERO(&fdset);
    FD_SET(fd, &fdset);
    timeout.tv_sec = 0;
    timeout.tv_usec = 1;
    //int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
     struct timeval *timeout);
    return select(fd+1, &fdset, NULL, NULL, &timeout) == 1 ? 1 : 0;
}

您现在可以在使用前检查文件描述符,例如为了清空文件描述符:

void empty_fd(int fd) {
    char buffer[1024];
    while (is_ready(fd)) {
        read(fd, buffer, sizeof(buffer));
    }
}

在您的情况下,使用 fileno(stdin)来获取stdin的文件描述符:

if (is_ready(fileno(stdin))) {
    /* read stuff from stdin will not block */
}

答案 1 :(得分:2)

  

我想知道将带有O_NONBLOCK标志的fctntl()应用于stdin描述符是否允许我在非阻塞模式下使用read()函数?

使用O_NONBLOCK运行stdin优于select。选择说有一些数据,但不是多少。有时候,无论队列中有多少数据,您都希望获得所有可用数据,但不能阻止。为每个角色运行选择看起来像很繁忙的工作...... O_NONBLOCK对我不起作用。它是一个内部标志,在大多数tty驱动程序中都没有暴露。

查看ioctl(...,FIONBIO)。它似乎完成了工作。

答案 2 :(得分:1)

我不确定你是否可以在stdin上设置O_NONBLOCK,但是select()poll()肯定会完成工作。

答案 3 :(得分:0)

feof(stdin)出了什么问题?

答案 4 :(得分:0)

是的,你可以使用select(零超时)。但是,您不需要将文件描述符设置为非阻塞 - 如果select告诉您文件描述符是可读的,那么它上面的read肯定不会阻塞。

因此,使用select进行文件描述符0轮询,如果它是可读的,read它。如果read返回0,则表示已关闭。