use*_*013 6 pipe shell-script buffer
有没有办法读取管道缓冲区中已有的所有内容,将它们通过管道传输到另一个程序,然后立即退出而无需等待更多输入?
它必须是二进制安全的。可以要求安装其他程序。
例如,下面的命令应该输出a
and not b
,并在第二个回声上引发 SIGPIPE (至少如果系统没有太多负载):
{ echo a; sleep 2s; echo b;} | { sleep 1s; my_command;}
Run Code Online (Sandbox Code Playgroud)
如果您read()
在管道上执行一个系统调用,如果管道中没有任何内容,它将挂起,否则会立即返回其中的内容。
现在,对于其中的内容,至少在我的 amd64 多核系统上使用 Linux 4.4(对于其他系统或其他版本的 Linux 来说是 YMMV),如果一个或多个进程当前正在write()
另一端执行(或其他写入系统调用),可能超过管道的容量(当前版本的 Linux 上默认为 64KiB),调度程序将在read()
系统调用期间在这些进程和从管道读取的进程之间来回多次,并且read()
返回的值可能比管道的容量大得多。管道容量。
该dd
命令是系统调用的 CLI 接口read
。
dd bs=1G count=1
Run Code Online (Sandbox Code Playgroud)
(请注意,并非所有dd
实现都支持这些G
后缀)read()
从 stdin 执行大小为 1GiB 的操作(后跟write()
stdout 上的一个)
使用 GNU dd
,您可以使用 避免空管道阻塞iflag=nonblock
。这会将管道设置为非阻塞模式,但请注意,它会使其之后保持非阻塞,这可能是不可取的。例如:
(date; sleep 2; date) |
(sleep 1
dd bs=1G count=1 status=none iflag=nonblock
wc -c)
Run Code Online (Sandbox Code Playgroud)
给:
Mon 23 Jan 22:11:30 GMT 2017
wc: 'standard input': Resource temporarily unavailable
0
Run Code Online (Sandbox Code Playgroud)
随着管道也变得不阻塞wc
。
正如前面所说,无论有没有nonblock
,您最终都会读到超出管道所能容纳的内容:
$ (cat /dev/zero & cat /dev/zero & cat /dev/zero) |
(sleep 1; dd bs=1G count=1) | wc -c
0+1 records in
0+1 records out
545914880 bytes (546 MB, 521 MiB) copied, 0.48251 s, 1.1 GB/s
545914880
Run Code Online (Sandbox Code Playgroud)
(并且从一次运行到下一次运行你会得到不同的数字)。
支持它的系统上的另一种方法是在执行读取之前使用FIONREAD
ioctl()
查询管道中有多少数据。
perl -e '
require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die "ioctl: $!\n";
$n = unpack "L", $n;
if ($n) {
sysread STDIN, $text, $n or die "read: $!\n";
print $text
}'
Run Code Online (Sandbox Code Playgroud)
请注意,因为它是分两步完成的,所以如果另一个进程同时从管道中读取数据,那么如果另一个进程清空 和 之间的管道,它可能仍然会ioctl()
阻塞read()
。
归档时间: |
|
查看次数: |
1641 次 |
最近记录: |