LinuxC,为什么fcntl对STDIN的作用也会对STDOUT和STDERR产生影响?
我在LinuxC,为什么fcntl对STDIN的作用也会对STDOUT和STDERR产生影响?,c,linux,C,Linux,我在stdin上执行功能fcntl时遇到了一个问题,当我将stdinFD状态标志设置为O_NONBLOCK时,它工作正常,但存在副作用。stdout和stderr的状态标志也已更改为O_NONBLOCK 我调查了函数fcntl、SYSCALL\u DEFINE3和do\u fcntl的源代码,但没有得到任何帮助。还有stackoverflow或google。我认为它可能与内核或GLUBC实现有关。 我的电脑是x86_64上的Ubuntu 12.04,安装在gcc 4.6.3中 int fla
stdin
上执行功能fcntl
时遇到了一个问题,当我将stdin
FD状态标志设置为O_NONBLOCK
时,它工作正常,但存在副作用。stdout和stderr的状态标志也已更改为O_NONBLOCK
我调查了函数fcntl
、SYSCALL\u DEFINE3
和do\u fcntl
的源代码,但没有得到任何帮助。还有stackoverflow或google。我认为它可能与内核或GLUBC实现有关。
我的电脑是x86_64上的Ubuntu 12.04,安装在gcc 4.6.3中
int flag = 0;
int value = O_NONBLOCK;
int fd = open("./tmp", O_RDONLY);
if(-1 == (flag = fcntl(fd, F_GETFL)))
fprintf(stdout, "%d:%s\n", errno, strerror(errno));
flag = fcntl(stdin->_fileno, F_GETFL);
flag = fcntl(stderr->_fileno, F_GETFL);
if(-1 == (flag = fcntl(stdout->_fileno, F_GETFL)))
fprintf(stdout, "%d:%s\n", errno, strerror(errno));
flag = fcntl(stdout->_fileno, F_SETFL, flag | O_NONBLOCK);
flag = fcntl(fd, F_GETFL);
flag = fcntl(stdin->_fileno, F_GETFL);
flag = fcntl(stdout->_fileno, F_GETFL);
flag = fcntl(stderr->_fileno, F_GETFL);
flag = fcntl(stdin->_fileno, F_SETFL, flag | O_APPEND);
flag = fcntl(fd, F_GETFL);
flag = fcntl(stdin->_fileno, F_GETFL);
flag = fcntl(stdout->_fileno, F_GETFL);
flag = fcntl(stderr->_fileno, F_GETFL);
close(fd);
这是我解决此问题的代码。登录过程(或终端打开过程)传统上使用的“技巧”之一是以读写模式打开文件描述符0(标准输入)的终端,然后复制文件描述符1和2(标准输出和标准错误)的终端。这意味着:
fcntl()
的F_GETFL和F_SETFL选项与打开的文件描述相关。
fcntl()
的F_GETFD和F_SETFD选项与文件描述符相关
给定的打开文件描述可能有多个文件描述符与之关联,或者在单个进程内(在
dup()
或dup2()
之后),或者跨进程(因为fork()
)。根据Jonathan的回答,以下是一些更明智的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
void show_nonblock_status(void) {
char streams[3][7] = {"stdin", "stdout", "stderr"};
for ( int i = 0; i < 3; ++i ) {
int flag = fcntl(i, F_GETFL);
if ( flag == -1 ) {
perror("error getting flags");
exit(EXIT_FAILURE);
}
if ( flag & O_NONBLOCK ) {
printf("O_NONBLOCK is set for %s\n", streams[i]);
} else {
printf("O_NONBLOCK is not set for %s\n", streams[i]);
}
}
}
int main(void) {
show_nonblock_status();
int flag = fcntl(1, F_GETFL);
if ( flag == -1 ) {
perror("error getting flags");
exit(EXIT_FAILURE);
}
flag = fcntl(1, F_SETFL, flag | O_NONBLOCK);
if ( flag == -1 ) {
perror("error getting flags");
exit(EXIT_FAILURE);
}
show_nonblock_status();
return 0;
}
在第一种情况下,文件描述是相同的,因此为所有三个设置了O_NONBLOCK
在第二种情况下,一个文件通过管道传输到stdin
,因此它与stdout
和stderr
具有不同的文件描述,这两种文件都设置了O_NONBLOCK
在第三种情况下,一个文件通过管道传输到
stdin
,而stderr
被重定向到/dev/null
,因此所有3个文件描述都是不同的,O_NONBLOCK
只为stdout设置了stdout
,发布一些代码怎么样?当您不使用tty(例如echo”“/您的程序
)时,您试过吗对谢谢我只是gdb a.out
,并显示标志,当设置O_NONBLOCK为stdout时,我得到了stdin和stderr都有O_NONBLOCK。它很混乱。~是的。谢谢,CSAPP说有三种类型的打开文件,文件描述符,xxx(我忘了它的名字,谁持有报价计数和偏移量)和vnode。只有一个打开的文件描述符。非常感谢,帮了很多忙。
paul@local:~/src/c/scratch$ ./fct
O_NONBLOCK is not set for stdin
O_NONBLOCK is not set for stdout
O_NONBLOCK is not set for stderr
O_NONBLOCK is set for stdin
O_NONBLOCK is set for stdout
O_NONBLOCK is set for stderr
paul@local:~/src/c/scratch$ cat testfile | ./fct
O_NONBLOCK is not set for stdin
O_NONBLOCK is not set for stdout
O_NONBLOCK is not set for stderr
O_NONBLOCK is not set for stdin
O_NONBLOCK is set for stdout
O_NONBLOCK is set for stderr
paul@local:~/src/c/scratch$ cat testfile | ./fct 2>/dev/null
O_NONBLOCK is not set for stdin
O_NONBLOCK is not set for stdout
O_NONBLOCK is not set for stderr
O_NONBLOCK is not set for stdin
O_NONBLOCK is set for stdout
O_NONBLOCK is not set for stderr
paul@local:~/src/c/scratch$