我正在进行一项任务,程序将文件描述符作为参数(通常来自exec调用中的父项)并从文件中读取并写入文件描述符,在我的测试中,我意识到程序将从命令行工作,如果我使用0,1或2作为文件描述符,则不会出错。这对我来说很有意义,除了我可以写入stdin并让它显示在屏幕上。
对此有解释吗?我一直认为在stdin / stdout上有一些保护,你当然不能从stdout到stdin或fgetsf fprintf。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
char message[20];
read(STDOUT_FILENO, message, 20);
write(STDIN_FILENO, message, 20);
return 0;
}
答案 0 :(得分:11)
尝试在标记为readonly或反之亦然的文件上写入会导致write
和read
返回-1,并失败。在这个特定的情况下,stdin和stdout实际上是同一个文件。实质上,在程序执行之前(如果你不进行任何重定向),shell会:
if(!fork()){
<close all fd's>
int fd = open("/dev/tty1", O_RDWR);
dup(fd);
dup(fd);
execvp("name", argv);
}
因此,stdin,out和err都是同一个文件描述符的副本,为读写而打开。
答案 1 :(得分:2)
read(STDIN_FILENO, message, 20);
write(STDOUT_FILENO, message, 20);
应该有效。注意 - stdout我与stdin不同(甚至在命令行上)。您可以将另一个进程的输出作为stdin提供给您进程,或者将stdin / stdout安排为文件。
fprintf / fgets有一个缓冲区 - 从而减少了系统调用次数。
答案 2 :(得分:1)
最佳猜测 - stdin指向输入的来源,终端和stdout指向输出应该到达的位置,终端。既然它们都指向同一个地方它们是可以互换的(在这种情况下)?
答案 3 :(得分:1)
如果您在UNIX上运行程序
myapp < input > output
你可以打开/ proc / {pid} / fd / 1并从中读取,打开/ proc / {pid} / fd / 0并写入它,例如,将output
复制到{{1 }}。 (可能有一种更简单的方法,但我知道它有效)
如果你坚持下去,你可以做任何容易混淆的事情。 ;)
答案 4 :(得分:0)
文件描述符0,1和2很可能都是开放的,用于读取和写入(实际上它们都引用相同的底层“打开文件描述”),在这种情况下你正在做什么将工作。但据我所知,没有保证,所以它也可能不起作用。我确实认为POSIX某处指定如果stderr在shell调用程序时连接到终端,它应该是可读写的,但是我找不到引用权。
一般来说,我建议不要读取stdout或stderr,除非你正在寻找一个终端来读取密码,并且stdin已被重定向(不是tty)。我建议永远不要写入stdin - 这很危险,你最终可能会破坏用户不希望写入的文件!