关于 ls、dir 和 tee 的混淆
A confusion about ls, dir and tee
我知道 tee
将从 STDIN 读取并创建一个新文件。但是当它带有 ls
时,哪个过程先发生?
例如:
➤ ls
12 123 1234
➤ ls | tee hello
12
123
1234
hello # ls catch hello
➤ ls | tee 000
12
123
1234
hello # ls didn't get 000
➤ ls | tee 0
000
12
123
1234
hello # ls didn't get 0
➤ ls | tee 00000
0
000
00000 # ls did get 00000
12
123
1234
hello
➤
但是说到 dir
:
➤ ls
12 123 1234
➤ dir | tee hello
12 123 1234 hello # get hello
➤ dir | tee 000
000 12 123 1234 hello
➤ dir | tee 0
0 000 12 123 1234 hello #get 0
➤ dir | tee 000000
0 000 12 123 1234 hello # didn't get 00000
➤ dir | tee 01
0 000 000000 01 12 123 1234 hello
➤ dir | tee 000000000000000000000000
0 000 000000 000000000000000000000000 01 12 123 1234 hello #get 00000000..000
➤
为什么?哪个先发生? tee
创建新文件或 ls
/dir
输出?
两个程序同时运行。当管道左侧的进程正在将输出写入管道时,管道右侧的进程正在从中读取。
tee
将在开始后立即创建输出文件,然后再从输入中读取。这就是为什么有时(!)可以在 ls
、 和 的输出中看到文件 dir
的输出。但是,不能保证。一般取决于每个进程什么时候进入the/aCPU以及循环多少次,打开文件需要等待多长时间tee
等等。
实际上在我的测试系统上,文件几乎总是显示为 ls
或 dir
。但有时列表中的文件又丢失了 ls
或 dir
.
这实际上是一个process-race-condition在一个directory-resource上的情况,因为两个进程都执行并行
Each command in a pipeline is executed as a separate process (i.e., in
a sub-shell).
管道的想法是将与可执行文件 exec_A 关联的进程 A 中的 output
重定向到与可执行文件 exec_B 关联的进程 B :
exec_A | exec_B
如何做到这一点在很大程度上取决于实现,但考虑到实际限制,操作系统必须创建一个缓冲区来放置 A 的输出并强制 B 从该缓冲区读取。这发生在进程开始之前。
所以发生的事情是这样的:
exec_A &> buf ; exec_B < buf &
进程在内部如何处理它们接收或写入的数据取决于进程的实现。在这种情况下,tee 正在创建将在进程启动时写入的文件,这绝对合乎逻辑,因为它需要附加传入数据。
鉴于此,这取决于进程 A(即 ls
/dir
)是否在进程 B 打开文件之前完成其目录遍历。这实际上取决于谁获得了资源父级的锁。
您实际上可以观察到 ls
几乎总是输出这样创建的资源:
ls * | tee subdir/0
因为它在 subdir
上获得了锁。
我知道 tee
将从 STDIN 读取并创建一个新文件。但是当它带有 ls
时,哪个过程先发生?
例如:
➤ ls
12 123 1234
➤ ls | tee hello
12
123
1234
hello # ls catch hello
➤ ls | tee 000
12
123
1234
hello # ls didn't get 000
➤ ls | tee 0
000
12
123
1234
hello # ls didn't get 0
➤ ls | tee 00000
0
000
00000 # ls did get 00000
12
123
1234
hello
➤
但是说到 dir
:
➤ ls
12 123 1234
➤ dir | tee hello
12 123 1234 hello # get hello
➤ dir | tee 000
000 12 123 1234 hello
➤ dir | tee 0
0 000 12 123 1234 hello #get 0
➤ dir | tee 000000
0 000 12 123 1234 hello # didn't get 00000
➤ dir | tee 01
0 000 000000 01 12 123 1234 hello
➤ dir | tee 000000000000000000000000
0 000 000000 000000000000000000000000 01 12 123 1234 hello #get 00000000..000
➤
为什么?哪个先发生? tee
创建新文件或 ls
/dir
输出?
两个程序同时运行。当管道左侧的进程正在将输出写入管道时,管道右侧的进程正在从中读取。
tee
将在开始后立即创建输出文件,然后再从输入中读取。这就是为什么有时(!)可以在 ls
、 和 的输出中看到文件 dir
的输出。但是,不能保证。一般取决于每个进程什么时候进入the/aCPU以及循环多少次,打开文件需要等待多长时间tee
等等。
实际上在我的测试系统上,文件几乎总是显示为 ls
或 dir
。但有时列表中的文件又丢失了 ls
或 dir
.
这实际上是一个process-race-condition在一个directory-resource上的情况,因为两个进程都执行并行
Each command in a pipeline is executed as a separate process (i.e., in a sub-shell).
管道的想法是将与可执行文件 exec_A 关联的进程 A 中的 output
重定向到与可执行文件 exec_B 关联的进程 B :
exec_A | exec_B
如何做到这一点在很大程度上取决于实现,但考虑到实际限制,操作系统必须创建一个缓冲区来放置 A 的输出并强制 B 从该缓冲区读取。这发生在进程开始之前。
所以发生的事情是这样的:
exec_A &> buf ; exec_B < buf &
进程在内部如何处理它们接收或写入的数据取决于进程的实现。在这种情况下,tee 正在创建将在进程启动时写入的文件,这绝对合乎逻辑,因为它需要附加传入数据。
鉴于此,这取决于进程 A(即 ls
/dir
)是否在进程 B 打开文件之前完成其目录遍历。这实际上取决于谁获得了资源父级的锁。
您实际上可以观察到 ls
几乎总是输出这样创建的资源:
ls * | tee subdir/0
因为它在 subdir
上获得了锁。