我对这三个文件的目的感到困惑。如果我的理解是正确的,stdin
是程序写入其在进程中运行任务的请求的文件,stdout
是内核写入其输出的文件以及请求它访问信息的进程,并且stderr
是输入所有例外的文件。在打开这些文件以检查这些文件是否确实发生时,我发现似乎没有任何建议!
我想知道的是这些文件的目的究竟是什么,用非常少的技术术语绝对愚蠢地回答!
标准输入 - 这是您的进程读取的文件句柄,以从您那里获取信息。
标准输出 - 您的进程将正常信息写入此文件句柄。
标准错误 - 您的进程将错误信息写入此文件句柄。
这就像我能做到的那样愚蠢:-)
当然,这主要是按照惯例。如果您愿意,没有什么可以阻止您将错误信息写入标准输出。您甚至可以完全关闭三个文件句柄并打开您自己的I / O文件。
当您的进程启动时,它应该已经打开了这些句柄,它只能读取和/或写入它们。
默认情况下,它们可能已连接到您的终端设备(例如,/dev/tty
),但shell将允许您在进程启动之前在这些句柄与特定文件和/或设备(甚至是其他进程的管道)之间建立连接(某些可能的操作是相当聪明的)。
一个例子是:
my_prog <inputfile 2>errorfile | grep XYZ
这将:
my_prog
创建一个流程。inputfile
作为标准输入(文件句柄0)。errorfile
作为标准错误(文件句柄2)。grep
创建另一个流程。my_prog
的标准输出附加到grep
的标准输入。你的评论:
当我在/ dev文件夹中打开这些文件时,为什么我永远不会看到正在运行的进程的输出?
这是因为它们不是普通文件。虽然UNIX在某个地方将文件系统中的所有文件都显示为文件,但这并不是最低级别的文件系统。 /dev
层次结构中的大多数文件都是字符或块设备,实际上是设备驱动程序。它们没有大小,但它们有一个主设备号和次设备号。
当您打开它们时,您已连接到设备驱动程序而不是物理文件,并且设备驱动程序足够聪明,可以知道应单独处理单独的进程。
Linux /proc
文件系统也是如此。这些不是真正的文件,只是严格控制内核信息的网关。
具有关联缓冲的文件称为流,并被声明为指向已定义类型FILE的指针。 fopen()函数为流创建某些描述性数据,并返回指针以指定所有其他事务中的流。通常,有三个开放流,在标头中声明了常量指针,并与标准打开文件相关联。在程序启动时,预定义了三个流,无需明确打开:标准输入(用于读取常规输入),标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。打开时,标准错误流未完全缓冲;当且仅当可以确定流不参考交互设备时,标准输入和标准输出流被完全缓冲
qazxswpoi
说stdin
,stdout
和stderr
是“I / O流”而不是文件更为正确。正如您所注意到的,这些实体并不存在于文件系统中。但就I / O而言,Unix哲学是“一切都是文件”。在实践中,这实际上意味着您可以使用相同的库函数和接口(printf
,scanf
,read
,write
,select
等),而无需担心I / O流是否连接到键盘,磁盘文件,套接字,管道或其他一些I / O抽象。
大多数程序需要读取输入,写入输出和日志错误,因此为您预定了stdin
,stdout
和stderr
,这是一种编程方便。这只是一种约定,并不是由操作系统强制执行的。
我担心你的理解是完全倒退的。 :)
从程序的角度考虑“标准输入”,“标准输出”和“标准错误”,而不是从内核的角度来看。
当程序需要打印输出时,它通常打印到“标准输出”。程序通常使用printf
将输出打印到标准输出,fprintf
仅打印到标准输出。
当程序需要打印错误信息时(不一定是异常,那些是编程语言结构,强加到更高的级别),它通常会打印到“标准错误”。它通常使用fopen
,它接受打印时使用的文件流。文件流可以是为写入而打开的任何文件:标准输出,标准错误或使用fdopen
或fread
打开的任何其他文件。
当文件需要使用fgets
或getchar
或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
读取输入时,使用“standard in”。
任何这些文件都可以从shell轻松重定向,如下所示:
cat < /etc/passwd > /tmp/out 2> /tmp/err
或者,整个辣酱玉米饼馅:
grep echo /etc/services | awk '{print $2;}' | sort
有两个重要的警告:第一,“标准输入”,“标准输出”和“标准错误”只是一种惯例。它们是一个非常强大的约定,但它只是一个协议,能够运行这样的程序非常好:FILE *
并将每个程序的标准输出挂钩到管道中下一个程序的标准输入。
其次,我给出了使用文件流(int
对象)的标准ISO C函数 - 在内核级别,它是所有文件描述符(read
对文件表的引用)和更低级别的操作,如write
和scanf(<formatstring>,<pointer to storage> ...);
,它不执行ISO C功能的快乐缓冲。我想保持简单并使用更简单的功能,但我认为你应该知道其他选择。 :)
通过控制台读取输入(例如键盘输入)。在C中使用scanf
printf(<string>, <values to print> ...);
生成输出到控制台。在C中使用printf
fprintf(stderr, <string>, <values to print> ...);
产生“错误”输出到控制台。在C中使用fprintf
echo < file.txt
stdin的源可以重定向。例如,它不是来自键盘输入,而是来自文件(ps | grep <userid>
)或其他程序(ls . > ls-output.txt
)。
stdout,stderr的目标也可以重定向。例如,可以将stdout重定向到文件:ls-output.txt
,在这种情况下,输出将写入文件Stderr can be redirected。 2>
与stderr
。
我认为人们说stdout
应该只用于错误信息是误导。
它还应该用于为运行命令的用户提供的信息性消息,而不是用于数据的任何潜在下游消费者(即,如果您运行shell管道链接几个命令,则不需要提供信息性消息,例如“获取项目30” 42424“将出现在this上,因为它们会使消费者感到困惑,但您可能仍希望用户看到它们。
有关历史原因,请参阅$ man stdout
:
“所有程序都在标准输出上放置了诊断功能。当输出被重定向到文件时,这总是会引起麻烦,但是当输出发送到毫无疑问的过程时变得无法容忍。但是,不愿违反标准输入的简单性 - 标准输出模型,人们通过v6容忍这种状态。此后不久,Dennis Ritchie通过引入标准错误文件来削减Gordian结。这还不够。管道诊断可能来自同时运行的几个程序中的任何一个。需要诊断表明自己。“
使用ps -aux显示当前进程,所有这些进程都在/ proc / as / proc /(pid)/中列出,通过调用cat / proc /(pid)/ fd / 0,它会打印在标准输出中找到的任何内容。我认为这个过程。或许,
/ proc /(pid)/ fd / 0 - 标准输出文件 / proc /(pid)/ fd / 1 - 标准输入文件 / proc /(pid)/ fd / 2 - 标准错误文件
例如
但是对于/ bin / bash只能很好地工作,其他进程通常在0中没有任何内容,但很多都有错误写入2
stderr不会执行IO Cache缓冲,所以如果我们的应用程序需要将关键消息信息(一些错误,异常)打印到控制台或文件使用它,使用stdout打印一般日志信息,因为它使用IO Cache缓冲有可能在将消息写入文件应用程序之前可能会关闭,从而使调试复杂
有关这些文件的权威信息,请查看手册页,在终端上运行命令。
https://www.mkssoftware.com/docs/man5/stdio.5.asp
但是对于一个简单的答案,每个文件用于:
stdout流出来的
stdin用于流输入
stderr用于打印错误或记录消息。
每个unix程序都有这些流中的每一个。