我可以增加系统管道缓冲区最大值吗?

我可以增加系统管道缓冲区最大值吗?

我想制作一个缓冲区约为 5MB 的 FIFO 管道。我知道 Linux 中默认的 FIFO 管道缓冲区最大值约为 1MB。我看到它位于 /proc/sys/fs/pipe-max-size

我尝试将其设置如下:

sudo sysctl fs.pipe-max-size=4194304

然后我看到值确实被改变了:

$ cat  /proc/sys/fs/pipe-max-size
4194304

然后我创建了一个新的 FIFO 管道,但我没有注意到性能有任何改进。它的填满速度似乎与之前的 1MB FIFO 管道相同。所以我不确定我的新 FIFO 管道实际上有 4MB 缓冲区。

我如何 1) 增加系统 FIFO 管道缓冲区最大值和 2) 创建使用此缓冲区最大值的 FIFO 管道?

答案1

您的命令更改最大缓冲区大小,而不是默认缓冲区大小。

来自管道(7) 联机帮助页

/proc/sys/fs/pipe-max-size(自 Linux 2.6.35 起)

不具有 CAP_SYS_RESOURCE 功能的用户可以设置的单个管道的最大大小(以字节为单位)。

和:

从Linux 2.6.11开始,管道容量为16页(即在页大小为4096字节的系统中为65,536字节)。从Linux 2.6.35开始,默认管道容量为16页,但可以使用fcntl(2)F_GETPIPE_SZF_SETPIPE_SZ操作来查询和设置容量。

因此,除非您fcntl(F_SETPIPE_SZ)在打开的管道上调用系统调用,否则它将保持默认容量:64 kB。为此,您必须使用一种提供系统调用绑定的语言(C/C++、Python、PHP、perl...但不是 sh/bash)。

答案2

根据 xhienne 的回答,此 perl 脚本将设置现有打开 fifo 的大小:

#!/usr/bin/perl
# usage: name-of-open-fifo size-in-bytes
# http://unix.stackexchange.com/a/353761/119298
use strict;
use Fcntl;
my $fifo = shift @ARGV or die "usage: fifo size";
my $size = shift @ARGV or die "usage: fifo size";
open(FD, $fifo) or die "cannot open";
printf "old size %d\n",fcntl(\*FD, Fcntl::F_GETPIPE_SZ, 0);
my $new = fcntl(\*FD, Fcntl::F_SETPIPE_SZ, int($size));
die "failed" if $new<$size;
printf "new size %d\n",$new;

将其放入一个文件中,例如~/setfifochmod +x对其执行操作,然后在创建并打开 fifo 后运行它,例如:

$ mkfifo /tmp/fifo
$ cat -n <>/tmp/fifo & 
$ ~/setfifo /tmp/fifo 1048576
 old size 65536
 new size 1048576

如果您的 Perl 还没有常量F_GETPIPE_SZF_SETPIPE_SZ,您可以使用通过查看 中的 C 文件找到的适当数字/usr/include/。分别是1024+8和1024+7。这是生成的 perl 脚本:

#!/usr/bin/perl
# usage: name-of-open-fifo size-in-bytes
# http://unix.stackexchange.com/a/353761/119298
use strict;
# int fcntl(int fd, int cmd, ...) F_GETPIPE_SZ,void F_SETPIPE_SZ,int
# /usr/include/asm-generic/fcntl.h #define F_LINUX_SPECIFIC_BASE 1024
# /usr/include/linux/fcntl.h #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
sub F_SETPIPE_SZ{ 1024+7; }
sub F_GETPIPE_SZ{ 1024+8; }
my $fifo = shift @ARGV or die "usage: fifo size";
my $size = shift @ARGV or die "usage: fifo size";
open(FD, $fifo) or die "cannot open";
printf "old size %d\n",fcntl(\*FD, F_GETPIPE_SZ, 0);
my $new = fcntl(\*FD, F_SETPIPE_SZ, int($size));
die "failed" if $new<$size;
printf "new size %d\n",$new;

相关内容