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