写入stdin并从stdout读取(UNIX / LINUX / C编程)
我正在做一个任务,一个程序把一个文件描述符作为参数(一般来自父调用exec调用),并从一个文件读取并写入一个文件描述符,在我的testing中,我意识到程序可以工作如果我使用0,1或2作为文件描述符,则不会发出错误。 这对我来说是有意义的,除了我可以写入标准input并显示在屏幕上。
有这个解释吗? 我一直认为stdin / stdout有一些保护,你肯定不能从标准输出到标准input或者fgets。
#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; }
试图在标记为只读的文件上写入或反之亦然会导致write
和read
返回-1,并失败。 在这个特定的情况下,stdin和stdout实际上是相同的文件。 实质上,在你的程序执行之前(如果你不做任何redirect),shell会执行:
if(!fork()){ <close all fd's> int fd = open("/dev/tty1", O_RDWR); dup(fd); dup(fd); execvp("name", argv); }
所以,stdin,out和err都是同一个文件描述符的副本,打开来读写。
read(STDIN_FILENO, message, 20); write(STDOUT_FILENO, message, 20);
应该工作。 注 – 标准输出我是一个从标准input(甚至在命令行)不同的地方。 您可以将来自另一个进程的输出作为标准input提供给您的进程,或将标准input/标准输出安排为文件。
fprintf / fgets有一个缓冲区 – 从而减less了系统调用的次数。
最好的猜测 – stdin指向input来自哪里,你的terminal和标准输出指向输出应该在哪里,你的terminal。 既然他们都指向相同的地方,他们是可以互换的(在这种情况下)?
如果你在UNIX上运行一个程序
myapp < input > output
你可以打开/ proc / {pid} / fd / 1并从中读取,打开/ proc / {pid} / fd / 0并写入,例如复制output
到input
。 (可能有一个简单的方法来做到这一点,但我知道它的工作原理)
如果你把自己的想法付诸实践,你可以做任何简单混淆的事情。 ;)
文件描述符0,1和2都是可以读写的(事实上它们都指向相同的底层“打开文件描述”),在这种情况下,你正在做的工作是很有可能的。 但据我所知,没有保证,所以也可能不起作用。 我确实相信POSIX某处指定,如果stderr连接到terminal,当程序被shell调用时,它应该是可读写的,但是我找不到引用。
一般来说,我会build议不要从stdout或stderr读取,除非你正在寻找一个terminal来读取密码,而stdin已被redirect(不是tty)。 而且我会build议不要写入标准input – 这是危险的,你最终可能会破坏用户不希望写入的文件!
如果你想写消息到stdin,你可以打开当前的tty,并调用write
系统调用来写消息到这个fd:
string console_cmd = "hello"; string tty = ttyname(STDIN_FILENO); int fd = open(tty.c_str(), O_WRONLY); write(fd, console_cmd.c_str(), console_cmd.size());
同样,从标准输出读取。