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

use*_*813 5 linux memory pipe buffer fifo

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

我尝试将其设置如下:

sudo sysctl fs.pipe-max-size=4194304
Run Code Online (Sandbox Code Playgroud)

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

$ cat  /proc/sys/fs/pipe-max-size
4194304
Run Code Online (Sandbox Code Playgroud)

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

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

xhi*_*nne 7

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

pipe(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)。


meu*_*euh 5

继 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;
Run Code Online (Sandbox Code Playgroud)

把它放在一个文件中,比如说~/setfifochmod +x在上面做,然后在你创建并打开你的 fifo 后运行它,例如:

$ mkfifo /tmp/fifo
$ cat -n <>/tmp/fifo & 
$ ~/setfifo /tmp/fifo 1048576
 old size 65536
 new size 1048576
Run Code Online (Sandbox Code Playgroud)

如果您的 perl 还没有常量F_GETPIPE_SZand F_SETPIPE_SZ,您可以使用通过查看/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;
Run Code Online (Sandbox Code Playgroud)