困惑关于stdin,stdout和stderr?

我很困惑这三个文件的目的。 如果我的理解是正确的, stdin是程序写入其请求中运行进程中的任务的文件。 stdout是内核写入其输出的文件,并且请求它访问来自stderr的信息, stderr是input所有exception的文件。 在打开这些文件来检查这些文件是否真的发生了,我发现似乎没有任何提示!

我想知道的是这些文件的目的究竟是什么,绝对愚蠢的回答用很less的科技术语!

标准input – 这是您的进程读取从您获取信息的文件句柄

标准输出 – 您的进程将正常信息写入此文件句柄。

标准错误 – 您的过程在此处写入错误信息。

这就像我可以做到的一样愚蠢:-)

当然,那大多是按照惯例。 如果你愿意的话,没有什么能够阻止你将你的错误信息写入标准输出。 您甚至可以完全closures这三个文件句柄,并打开自己的I / O文件。

当你的进程启动时,它应该已经打开这些句柄,它可以读取和/或写入它们。

默认情况下,它们可能连接到你的terminal设备(例如/dev/tty ),但是在你的进程之前,shell将允许你在这些句柄和特定的文件和/或设备之间build立连接(甚至是连接到其他进程的pipe道)开始(一些操作可能是相当聪明的)。

一个例子是:

 my_prog <inputfile 2>errorfile | grep XYZ 

这将:

  • my_prog创build一个进程。
  • 打开input文件作为标准input(文件句柄0)。
  • 打开错误文件作为您的标准错误(文件句柄2)。
  • grep创build另一个进程。
  • my_prog的标准输出my_proggrep的标准input。

重新评论:

当我在/ dev文件夹中打开这些文件时,我怎么从来没有看到正在运行的进程的输出?

这是因为他们不是正常的文件。 尽pipeUNIX将所有内容都呈现为某个文件系统中的某个文件,但这并不是最低级别的文件系统。 /dev层次结构中的大多数文件都是字符或块设备,实际上是设备驱动程序。 他们没有大小,但他们有一个主要和次要的设备号码。

当你打开它们时,你连接到设备驱动程序而不是物理文件,设备驱动程序足够聪明,知道应该单独处理单独的进程。

Linux /proc文件系统也是如此。 这些不是真正的文件,只是严格控制内核信息的网关。

stdinstdoutstderr是“I / Ostream”而不是文件是更正确的。 正如你所注意到的,这些实体不在文件系统中。 但就I / O而言,Unix哲学就是“一切都是文件”。 实际上,这实际上意味着您可以使用相同的库函数和接口( printfscanfreadwriteselect等),而不用担心I / Ostream是否连接到键盘,磁盘文件,套接字,pipe道或其他I / O抽象。

大多数程序需要读取input,写入输出和日志错误,因此为了方便编程, stdinstdoutstderr是为您预定义的。 这只是一个惯例,并不是由操作系统强制执行的。

恐怕你的理解完全倒退了。 🙂

程序的angular度来考虑“标准入门”,“标准出局”和“标准错误”,而不是从内核的angular度来看。

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

当一个程序需要打印错误信息(不一定是例外,这些是一个编程语言结构,强加在更高的层面上),通常打印到“标准错误”。 它通常使用fprintf ,它接受打印时使用的文件stream。 文件stream可以是任何打开的文件:标准输出,标准错误或用fopenfdopen打开的任何其他文件。

当文件需要读取input时,使用“standard in”,使用freadfgetsgetchar

这些文件中的任何一个都可以轻松地从shell中redirect ,如下所示:

 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 grep echo /etc/services | awk '{print $2;}' | sort 将每个程序的标准输出挂钩到stream水线中下一个程序的标准input中。

其次,我已经提供了用于处理文件stream( FILE *对象)的标准ISO C函数 – 在内核级别,它是所有文件描述符(对文件表的int引用)和更低级的操作,比如readwrite ,这不会做ISO C函数的快乐缓冲。 我想保持简单,并使用更简单的function,但我认为,你应该知道的替代品。 🙂

标准input

通过控制台读取input(例如键盘input)在C中使用scanf

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

标准输出

产生输出到控制台在C中使用printf

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

标准错误

生成“错误”输出到控制台在C中使用fprintf

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

redirect

stdin的源可以被redirect。 例如,不是来自键盘input,而是来自文件( echo < file.txt )或其他程序( ps | grep <userid> )。

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

使用ps -aux通过调用cat / proc /(pid)/ fd / 0显示当前进程,所有这些进程都列在/ proc / as / proc /(pid)/中,它打印任何在标准输出我认为这个过程。 或许,

/ proc /(pid)/ fd / 0 – 标准输出文件
/ proc /(pid)/ fd / 1 – 标准input文件
/ proc /(pid)/ fd / 2 – 标准错误文件

例如 我的终端窗口

但是只对/ bin / bash工作起来很好,其他进程通常在0中什么都没有,但是很多有错误写在2中

我认为人们说stderr应该只用于错误信息是有误导性的。 它也应该用于为用户运行命令的信息消息,而不是为数据的任何潜在的下游消费者(即,如果你运行一个shellpipe道链接几个命令,你不需要像“获取项目30” 42424“出现在标准输出上,因为它们会混淆消费者,但是您可能仍然希望用户看到它们。

历史原理见http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout

“所有的程序都把诊断放在标准输出上,当输出被redirect到一个文件时,总是会引起麻烦,但是当输出发送到一个不知情的进程时,却变得不能容忍,但是不愿意违背标准input – 标准输出模型,人们可以通过v6来容忍这种状态,此后不久,Dennis Ritchie通过引入标准错误文件来削减Gordian结,这还不够,pipe道诊断可能来自同时运行的多个程序中的任何一个。自我认同“。

具有关联缓冲的文件被称为stream,并被声明为指向定义typesFILE的指针。 fopen()函数为stream创build特定的描述性数据,并返回一个指针指向所有后续事务中的stream。 通常有三个打开的​​stream,在头文件中声明常量指针并与标准的打开文件关联。 在程序启动时,预定义了三个stream,不需要明确打开:标准input(用于读取常规input),标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。 标准错误stream打开时没有完全缓冲; 标准input和标准输出stream是完全缓冲的,当且仅当stream可以被确定为不涉及交互设备时

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