Linux 对于STDIN_FILENO和STDOUT_FILENO,非阻塞I/O行为很奇怪

Linux 对于STDIN_FILENO和STDOUT_FILENO,非阻塞I/O行为很奇怪,linux,nonblocking,Linux,Nonblocking,我有以下代码: void set_fl(int fd, int flags) /* flags are file status flags to turn on */ { int val; if ((val = fcntl(fd, F_GETFL, 0)) < 0) err_sys("fcntl F_GETFL error"); val |= flags; /* turn on flags */ if (fcntl(fd,

我有以下代码:

void
set_fl(int fd, int flags) /* flags are file status flags to turn on */
{
    int val;

    if ((val = fcntl(fd, F_GETFL, 0)) < 0)
        err_sys("fcntl F_GETFL error");

    val |= flags;       /* turn on flags */

    if (fcntl(fd, F_SETFL, val) < 0)
        err_sys("fcntl F_SETFL error");
}

int
main(void)
{
    char buf[BUFSIZ];
    set_fl(STDOUT_FILENO, O_NONBLOCK);  //set STDOUT_FILENO to nonblock
    if(read(STDIN_FILENO, buf, BUFSIZ)==-1) { //read from STDIN_FILENO
        printf("something went wrong with read()! %s\n", strerror(errno));
    }
}

谢谢

这完全正确:读取后立即打印
errno
和调用
perror
会导致“资源繁忙”和错误编号11,或
EAGAIN/ewoodblock
,如下代码所示:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

int main (void) {
    char buf;

    fcntl (STDOUT_FILENO, F_SETFL, fcntl (STDOUT_FILENO, F_GETFL, 0) | O_NONBLOCK);
    fprintf (stderr, "%5d: ", errno); perror("");
    read (STDIN_FILENO, &buf, 1);
    fprintf (stderr, "%5d: ", errno); perror("");
}
原因是文件描述符有两种不同类型的标志(请参阅详细介绍复制文件描述符的部分):

您可以复制一个文件描述符,或分配另一个文件描述符,该文件描述符引用与原始文件相同的打开文件。重复描述符共享一个文件位置和一组文件状态标志(请参见文件状态标志),但每个描述符都有自己的一组文件描述符标志(请参见描述符标志)

第一个是每个文件描述符都是唯一的。根据文档,
FD_CLOEXEC
(关闭
exec
)是目前该阵营中唯一的一个

所有其他标志都是,并且在已复制的文件描述符之间共享。这些包括诸如
O_NONBLOCK

因此,这里发生的是,标准输出文件描述符是从标准输入文件描述符复制的(顺序不相关,只是一个从另一个复制的事实),因此在一个上设置非阻塞模式会影响所有复制(这可能还包括标准错误文件描述符,尽管我还没有确认)

在重复的文件描述符上使用阻塞模式,或者在子进程可能继承的文件描述符上使用阻塞模式,通常都不是一个好主意-这些子进程并不总是乐于让标准文件出现错误(从它们的角度来看)


如果您希望对单个文件描述符进行更细粒度的控制,请考虑在尝试读取之前使用<代码>选择< /代码>检查描述符。< / P>检查返回值和ErNO,以找出为什么?程序是在伪终端中运行,还是用I/O重定向,或是什么?ErrNO是11,我在UBUNT的终端上运行它。uso所有重复描述符都像指针一样工作,对吗?它们不能有自己的文件状态flags@camino:就像我8岁的儿子会说的,是的,我强调“重复”-独立打开的文件,例如,使用
打开
,彼此不共享文件状态标志-至少可以说,这相当烦人。
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

int main (void) {
    char buf;

    fcntl (STDOUT_FILENO, F_SETFL, fcntl (STDOUT_FILENO, F_GETFL, 0) | O_NONBLOCK);
    fprintf (stderr, "%5d: ", errno); perror("");
    read (STDIN_FILENO, &buf, 1);
    fprintf (stderr, "%5d: ", errno); perror("");
}
    0: Success
   11: Resource temporarily unavailable