我对这三个文件的用途感到相当困惑。如果我的理解是正确的,stdin是程序写入它的请求以在进程中运行任务的文件,stdout是内核写入它的输出和它访问的请求进程的信息的文件,stderr是所有异常都输入的文件。在打开这些文件来检查这些是否真的发生了,我发现似乎没有什么建议!

我想知道的是这些文件的确切目的是什么,绝对愚蠢的答案与很少的技术术语!


当前回答

It would be more correct to say that stdin, stdout, and stderr are "I/O streams" rather than files. As you've noticed, these entities do not live in the filesystem. But the Unix philosophy, as far as I/O is concerned, is "everything is a file". In practice, that really means that you can use the same library functions and interfaces (printf, scanf, read, write, select, etc.) without worrying about whether the I/O stream is connected to a keyboard, a disk file, a socket, a pipe, or some other I/O abstraction.

大多数程序都需要读取输入,写入输出,并记录错误,所以stdin, stdout, 和stderr是为您预定义的,以方便编程。这只是 一种约定,操作系统不强制执行。

其他回答

A file with associated buffering is called a stream and is declared to be a pointer to a defined type FILE. The fopen() function creates certain descriptive data for a stream and returns a pointer to designate the stream in all further transactions. Normally there are three open streams with constant pointers declared in the header and associated with the standard open files. At program startup three streams are predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). When opened the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device

https://www.mkssoftware.com/docs/man5/stdio.5.asp

作为上述答案的补充,以下是关于重定向的总结:

编辑:这张图并不完全正确。

第一个例子根本没有使用stdin,它将“hello”作为参数传递给echo命令。

图表还显示,2>&1与&>具有相同的效果

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

这是因为&>需要重定向到一个文件,而2>&1只是将stderr发送到stdout

下面是一篇关于stdin, stdout和stderr的长篇文章:

Linux中的stdin、stdout和stderr是什么?

总结:

Streams Are Handled Like Files Streams in Linux—like almost everything else—are treated as though they were files. You can read text from a file, and you can write text into a file. Both of these actions involve a stream of data. So the concept of handling a stream of data as a file isn’t that much of a stretch. Each file associated with a process is allocated a unique number to identify it. This is known as the file descriptor. Whenever an action is required to be performed on a file, the file descriptor is used to identify the file. These values are always used for stdin, stdout, and stderr: 0: stdin 1: stdout 2: stderr

具有讽刺意味的是,我在堆栈溢出和上面的文章中发现了这个问题,因为我正在搜索关于异常/非标准流的信息。所以我的探索还在继续。

恐怕你的理解完全落后了。:)

从程序的角度考虑“标准输入”、“标准输出”和“标准错误”,而不是从内核的角度考虑。

当一个程序需要打印输出时,它通常会打印到“标准输出”。程序通常使用printf将输出输出打印到标准输出,printf仅打印到标准输出。

当程序需要打印错误信息时(不一定是异常,那些是编程语言的结构,在更高的级别上强加),它通常打印为“标准错误”。它通常使用fprintf来实现,fprintf接受打印时使用的文件流。文件流可以是任何打开用于写入的文件:标准输出、标准错误或任何其他已使用fopen或fdopen打开的文件。

当文件需要读取输入时,使用"standard in",使用fread或fgets或getchar。

这些文件中的任何一个都可以很容易地从shell重定向,就像这样:

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

或者,整个玉米卷饼:

cat < /etc/passwd > /tmp/out 2> /tmp/err

这里有两个重要的警告:首先,“标准输入”、“标准输出”和“标准错误”只是一种约定。它们是一个非常强大的约定,但它只是一个协议,能够运行这样的程序是非常好的:grep echo /etc/services | awk '{print $2;}' | sort,并将每个程序的标准输出连接到管道中下一个程序的标准输入。

其次,我给出了用于处理文件流(file *对象)的标准ISO C函数——在内核级别,它是所有的文件描述符(文件表的int引用)和更低级的操作,如读和写,它们不像ISO C函数那样进行愉快的缓冲。我想保持简单,使用更简单的函数,但我认为你仍然应该知道替代方案。:)

stdin

通过控制台读取输入(例如键盘输入)。 在C语言中使用scanf

scanf(<formatstring>,<pointer to storage> ...);

stdout

产生输出到控制台。 在C中与printf一起使用

printf(<string>, <values to print> ...);

stderr

向控制台输出“错误”。 在C中与fprintf一起使用

fprintf(stderr, <string>, <values to print> ...);

重定向

stdin的源可以被重定向。例如,它不是来自键盘输入,而是来自文件(echo < file.txt)或另一个程序(ps | grep <userid>)。

stdout、stderr的目的地也可以重定向。例如,stdout可以重定向到一个文件:ls。> ls-output.txt,在这种情况下输出被写入文件ls-output.txt。Stderr可以用2>重定向。