Stellen Sie die Pipe-Kapazität unter Linux ein

7

Gibt es eine Möglichkeit, die Rohrkapazität von Rohren festzulegen, die in einem Bash-Skript (oder einem anderen Shell-Skript) definiert sind? Nehmen Sie z

cmd1 | cmd2

In neueren Linux-Versionen ist die Pipe-Kapazität standardmäßig auf 64 KB eingestellt. Ich weiß, dass ich die zwischen den beiden Prozessen "gepufferte" Datenmenge auf zwei Arten steuern kann:

  1. Verwenden von buffer(1): zcmd1 | buffer | cmd2
  2. Verwendung fcntl(2)mit der F_SETPIPE_SZFlagge von innen cmd1odercmd2

Jede Lösung hat Nachteile: bufferKann nur zum Erhöhen des Puffers verwendet werden; Für Schreibvorgänge über die Standard-Pipe-Kapazität muss der Downstream-Befehl weiterhin aktiviert werden. fcntlkann, soweit ich weiß, nur von innen cmd1oder von innen aufgerufen werden cmd2.

Meine Frage ist: Gibt es eine Möglichkeit, wenn die Shell das Rohr erstellt, in der Shell anzugeben, wie viel Kapazität das Rohr haben soll?

CAFxX
quelle
1
Eng verwandt: Erhöhen Sie die FIFO-Größenbeschränkung
Stéphane Chazelas
@ StéphaneChazelas, danke für den Hinweis, denn jetzt habe ich den Ansatz von dir und DepressedDaniel angepasst. Wenn niemand anderes eine bessere Antwort findet, werde ich einfach meinen Ausschnitt posten.
CAFxX

Antworten:

4

Für das Schreiben über die Standard-Pipe-Kapazität muss der Downstream-Befehl weiterhin aktiviert werden

Wenn Ihr Ziel nicht darin besteht, den Downstream-Befehl zu oft zu aktivieren, haben Sie versucht, die -pOption zu verwenden buffer? Es sollte dazu führen buffer, dass Schreibvorgänge angehalten werden, bis der Puffer zu einem bestimmten Prozentsatz gefüllt ist. Möglicherweise benötigen Sie auch die -sOption, um große Blöcke zu schreiben.

Update: Oh, die Pipes zwischen den Befehlen schränken die Dinge immer noch ein. Versuchen Sie möglicherweise, das folgende Adapterprogramm zu verwenden:

#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);
}

wie in:

adapter 1 (BIGSIZE) cmd1 | cmd2

oder auch:

adapter 1 (BIGSIZE) cmd1 | adapter 1 (BIGSIZE) buffer [args] | cmd2

wenn cmd1noch kleine schreibt.

DepressedDaniel
quelle
Mit Downstream-Befehl meinte ich buffer. cmd1kann nicht mehr als 64 KB (die Pipe-Kapazität) schreiben, bevor bufferes aufwachen muss. Und das gilt natürlich auch zwischen bufferund cmd2, da die Rohrkapazität immer 64KB beträgt.
CAFxX
@CAFxX Oh, ich verstehe deinen Standpunkt jetzt. Aktualisierung.
DepressedDaniel
1

Aufgrund der Vorschläge von DepressedDaniel und Stéphane Chazelas entschied ich mich für das, was einem Oneliner am nächsten kam:

function hugepipe {
  perl -MFcntl -e 'fcntl(STDOUT, 1031, 1048576) or die $!; exec { $ARGV[0] } @ARGV or die $!' "$@"
}

Dies ermöglicht Folgendes:

hugepipe <command> | <command>

und die Pipe zwischen den beiden Befehlen wird die Kapazität haben, die über das fcntlim Perl-Skript angegebene angegeben ist.

CAFxX
quelle