有没有办法设置 Bash(或其他 shell)脚本中定义的管道的管道容量?拿例如
cmd1 | cmd2
在最近的 Linux 中,管道容量默认设置为 64KB。我知道我可以通过两种方式控制两个进程之间“缓冲”的数据量:
- 使用
buffer(1)
:例如cmd1 | buffer | cmd2
fcntl(2)
与F_SETPIPE_SZ
内部cmd1
或内部的标志一起使用cmd2
每种解决方案都有缺点:buffer
只能用于增加缓冲区;同样写入默认管道容量仍需要唤醒下游命令。fcntl
据我所知,只能从内部调用cmd1
或cmd2
。
我的问题是:有没有办法,当外壳创建管道时,在外壳中指定管道应具有多少容量?
答案1
写入默认管道容量仍需要唤醒下游命令
如果您的目标不是太频繁地唤醒下游命令,您是否尝试使用该-p
选项buffer
?它应该导致buffer
保持写入,直到缓冲区被填充到一定百分比。您可能-s
还需要该选项来写入大块。
更新:哦,命令之间的管道仍然限制一些事情。也许尝试使用以下适配器程序:
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char** argv)
{
fcntl(atoi(argv[1]), F_SETPIPE_SZ, atoi(argv[2]));
execvp(argv[3],argv+3);
while (1);
}
如:
adapter 1 (BIGSIZE) cmd1 | cmd2
甚至:
adapter 1 (BIGSIZE) cmd1 | adapter 1 (BIGSIZE) buffer [args] | cmd2
如果cmd1
仍然进行小写入。
答案2
根据 DepressedDaniel 和 Stéphane Chazelas 的建议,我选择了我能找到的最接近 oneliner 的东西:
function hugepipe {
perl -MFcntl -e 'fcntl(STDOUT, 1031, 1048576) or die $!; exec { $ARGV[0] } @ARGV or die $!' "$@"
}
这允许执行以下操作:
hugepipe <command> | <command>
两个命令之间的管道将具有通过fcntl
perl 脚本中指定的容量。