Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are stdin and stdout seemingly interchangeable?

I understand that stdin and stdout (at least in UNIX parlance) are stream buffers, and that stdout is used to output from a program to the console (or to then be piped by a shell, etc), and that stdin is for standard input to a program..

So why is it, at least on macOS, that they can be used interchangeably (stdout as stdin, and vice versa?

Examples:

  1. If you run cat /dev/stdin then type something in, and it echoes it back. Running the command as cat /dev/stdout does the same thing.

  2. Similarly, echo "Hey There" > /dev/stdout and echo "Hey There" > /dev/stdin both output 'Hey There' back to the terminal.

  3. It also works in C++:

example:

#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;
}

When prompted, typing a single word, followed by EOF (Ctrl+D) works as expected.

like image 589
TheInnerParty Avatar asked Nov 23 '16 02:11

TheInnerParty


People also ask

How does stdin and stdout work?

stdin − It stands for standard input, and is used for taking text as an input. stdout − It stands for standard output, and is used to text output of any command you type in the terminal, and then that output is stored in the stdout stream.

What are stdin and stdout of the new process?

stdin / stdout are logical names for open files that are forwarded (or initialized) by the process that has started a given process. Actually, with the standard fork-and-exec pattern the setup of those may occur already in the new process (after fork) before exec is being called.

Does each process have its own stdin?

Processes have their own stdout, stderr, stdin channels where they can read/write.

Why do we use stdin?

stdin is an "input stream", which is an abstract term for something that takes input from the user or from a file. It is an abstraction layer sitting on top of the actual file handling and I/O. The purpose of streams is mainly to make your code portable between different systems.


1 Answers

Because, typically, when a program is invoked from an interactive terminal, with no redirection, both standard input and standard output are connected to the same terminal device, such as /dev/tty (the actual device name varies based on the operating system).

The terminal device is a read/write device. Reading from the terminal device reads terminal input. Writing to the terminal device generates output on the terminal.

You still have discrete file descriptors, 0 and 1, but they're connected to the same device.

Think of it as single, bi-directional pipe, that's duped to both file descriptors 0 and 1.

Linux behaves the same way (you can echo Foo >/dev/stdin and see the output):

$ 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

So, for this process, file descriptors 0 and 1 is connected to the /dev/pts/1, the same pseudo-terminal device. Whether you are reading from file descriptor 0 or file descriptor 1, you end up reading from the same underlying /dev device, so it makes no difference which actual file descriptor you use.

This is, of course, operating system-dependent. Other POSIX-based operating systems may implement their standard input and output in other ways, where you can't actually write to standard input and read from standard output.

like image 174
Sam Varshavchik Avatar answered Sep 30 '22 06:09

Sam Varshavchik