use*_*828 12 linux files stdout
我刚开始学习Linux 上的一切都是文件TM,这让我想知道如果我真的从 /dev/stdout 读取会发生什么:
$ cat /dev/stdout
^C
$ tail /dev/stdout
^C
Run Code Online (Sandbox Code Playgroud)
(这^C是我在程序挂起后杀死程序)。
当我尝试使用 时vim,我收到了不可思议的消息:“/dev/stdout”不是文件。喘气!
那么,当我尝试阅读这些“文件”时,为什么会出现挂断或错误消息?
lcd*_*047 11
为什么我会挂断电话
您不会从cat(1)和获得“挂断” tail(1),它们只是阻止读取。 cat(1)等待输入,并在看到完整行后立即打印:
$ cat /dev/stdout
foo
foo
bar
bar
Run Code Online (Sandbox Code Playgroud)
我在这里输入fooEnterbarEnterCTRL- D。
tail(1)等待输入,并仅在检测到时才打印EOF:
$ tail /dev/stdout
foo
bar
foo
bar
Run Code Online (Sandbox Code Playgroud)
在这里我再次输入fooEnterbarEnterCTRL- D。
或错误信息
Vim 是唯一一个给你一个错误的。它这样做是因为它针对运行 ,并且发现它没有设置该位。stat(2)/dev/stdoutS_IFREG
/dev/stdout是一个文件,但不是一个普通文件。事实上,内核中有一些舞蹈可以在文件系统中给它一个入口。在 Linux 上:
$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May 8 19:42 /dev/stdout -> /proc/self/fd/1
Run Code Online (Sandbox Code Playgroud)
在 OpenBSD 上:
$ ls -l /dev/stdout
crw-rw-rw- 1 root wheel 22, 1 May 7 09:05:03 2015 /dev/stdout
Run Code Online (Sandbox Code Playgroud)
在 FreeBSD 上:
$ ls -l /dev/stdout
lrwxr-xr-x 1 root wheel 4 May 8 21:35 /dev/stdout -> fd/1
$ ls -l /dev/fd/1
crw-rw-rw- 1 root wheel 0x18 May 8 21:35 /dev/fd/1
Run Code Online (Sandbox Code Playgroud)
(几乎)一切都是文件,但并非一切都是常规文件。在目录、网络套接字、串行端口等特殊文件上调用文本编辑器是没有意义的。
/dev/stdout根据 unix 变体,该文件可以是以下几件事之一:
在任何情况下,打开/dev/stdout和类似的文件都会创建一个新的文件描述符,该文件描述符与应用程序已在文件描述符 1 上打开的同一文件相关联。“标准输出”表示文件描述符 1,并且使用此文件描述符只是约定对于输出——内核不在乎。
当您在终端中运行程序时,所有三个标准描述符(0 = 标准输入,1 = 标准输出,2 = 标准错误)都在终端设备上打开。从该设备读取返回用户键入的字符,写入该设备在终端窗口中显示文本。(给定终端设备,没有标准方法来读取它显示的输出或将输入注入其中。)
当你运行时cat /dev/stdout,它和cat /dev/stdinor做的事情完全一样cat /dev/stderr,因为这三个文件描述符连接到同一个文件:它告诉cat从终端读取。这也是cat没有争论的事情。
如果您运行cat /dev/stdout >foo,/dev/stdout则将引用该文件foo- 该命令等效于cat foo >foo. 根据cat实现,它可能会出错(GNU 版本抱怨“输入文件是输出文件”),或者它可能什么都不做,因为它从foo空文件中读取(>foo只是截断了它)。如果版本cat不检测这种特殊情况,则如果foo不为空,则cat /dev/stdout >>foo或等价物cat foo >>foo将无限期地将文件的内容附加到自身。
当您运行时vim /dev/stdout,它会抱怨,因为它不知道如何编辑终端(这没有意义)。