为什么stdin和stdout看似可以互换?

时间:2016-11-23 02:30:45

标签: c++ macos shell unix stdout

我知道stdin和stdout(至少在UNIX用语中)是流缓冲区,而stdout用于从程序输出到控制台(或者由shell管道等),而stdin是用于程序的标准输入..

那么为什么至少在macOS上它们可以互换使用(stdout作为stdin,反之亦然?

示例:

  1. 如果你运行cat /dev/stdin然后输入内容,它会回复它。以cat /dev/stdout运行命令也可以做同样的事情。

  2. 同样,echo "Hey There" > /dev/stdoutecho "Hey There" > /dev/stdin都会将“嘿那里”输出回终端。

  3. 它也适用于C ++:

  4. 示例:

    #include <iostream>
    #include <string>
    #include <fstream>
    
    int main(int argc, const char * argv[]) {
        std::string echoString;
        std::fstream stdoutFile;
        stdoutFile.open("/dev/stdout");
        stdoutFile << "Hey look! I'm using stdout properly!\nNow You trying using it wrongly: " << std::endl;
        stdoutFile >> echoString;
        stdoutFile << "You Typed: " << echoString << std::endl;
    }
    

    出现提示时,键入单个单词,然后按EOF(Ctrl + D)按预期工作。

2 个答案:

答案 0 :(得分:3)

因为,通常,当从交互式终端调用程序而没有重定向时,标准输入和标准输出都连接到同一终端设备,例如/dev/tty(实际设备名称根据操作系统)。

终端设备是读/写设备。从终端设备读取读取终端输入。写入终端设备会在终端上生成输出。

您仍然拥有离散文件描述符0和1,但它们已连接到同一设备。

将其视为单个双向管道,dup为文件描述符0和1。

Linux的行为方式相同(您可以echo Foo >/dev/stdin并查看输出):

$ ls -al /proc/self/fd/[01]
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/0 -> /dev/pts/1
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/1 -> /dev/pts/1

因此,对于此过程,文件描述符0和1连接到/dev/pts/1,即相同的伪终端设备。无论您是从文件描述符0还是文件描述符1读取,您最终都会从同一个底层/dev设备读取,因此您使用的实际文件描述符没有区别。

当然,这取决于操作系统。其他基于POSIX的操作系统可能以其他方式实现其标准输入和输出,您无法实际写入标准输入并从标准输出读取。

答案 1 :(得分:0)

正如你所说,它们只是流缓冲区。没有任何关于他们强制执行特定使用模式 - 只是惯例。流缓冲区stdin,stdout和stderr都是为了方便编程而提供的。