Posso aumentar o buffer do canal do sistema no máximo?

3

Eu gostaria de fazer um pipe FIFO com um buffer de ~ 5MB. Eu sei que o buffer de canal FIFO máximo no linux é em torno de 1MB. Vejo que ele mora em / proc / sys / fs / pipe-max-size

Eu tentei defini-lo da seguinte forma:

sudo sysctl fs.pipe-max-size=4194304

Depois, vejo que o valor foi realmente alterado:

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

Depois, criei um novo pipe FIFO, mas não notei nenhuma melhora no desempenho. Parece encher na mesma velocidade que o tubo FIFO anterior de 1MB. Então, não tenho certeza se o meu novo pipe FIFO tem um buffer de 4MB.

Como faço para 1) aumentar o buffer de canal FIFO do sistema max e 2) Criar um pipe FIFO que use esse buffer max?

    
por user2989813 25.03.2017 / 02:16

2 respostas

2

Seu comando altera o tamanho máximo do buffer, não o padrão.

Na página de manual do pipe (7) :

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

The maximum size (in bytes) of individual pipes that can be set by users without the CAP_SYS_RESOURCE capability.

e:

Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes in a system with a page size of 4096 bytes). Since Linux 2.6.35, the default pipe capacity is 16 pages, but the capacity can be queried and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations.

Assim, a menos que você chame a chamada de sistema fcntl(F_SETPIPE_SZ) no canal aberto, ela permanecerá com sua capacidade padrão: 64 kB. Para isso, você deve usar uma linguagem que ofereça uma ligação ao syscalls (C / C ++, Python, PHP, perl, ... mas não sh / bash).

    
por 25.03.2017 / 04:19
2

Seguindo a resposta de xhienne, este script perl definirá o tamanho de um fifo aberto existente:

#!/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;

Coloque isso em um arquivo, diga ~/setfifo , faça chmod +x , e execute-o depois de ter criado e aberto seu fifo, por exemplo:

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

Se o seu perl ainda não tiver as constantes F_GETPIPE_SZ e F_SETPIPE_SZ , você pode simplesmente usar os números apropriados encontrados procurando pelos arquivos C em /usr/include/ . São respectivamente 1024 + 8 e 1024 + 7. Aqui está o script perl resultante:

#!/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;
    
por 25.03.2017 / 09:53