web-dev-qa-db-ja.com

Linuxでパイプ容量を設定する

Bash(または他のシェル)スクリプトで定義されたパイプのパイプ容量を設定する方法はありますか?たとえば、.

_cmd1 | cmd2_

最近のLinuxでは、パイプ容量はデフォルトで64KBに設定されています。 2つのプロセス間で「バッファリング」されるデータの量を2つの方法で制御できることを私は知っています。

  1. buffer(1)の使用:例: _cmd1 | buffer | cmd2_
  2. _F_SETPIPE_SZ_または_cmd1_の内部から_cmd2_フラグを指定してfcntl(2)を使用する

各ソリューションには欠点があります。bufferはバッファーを増やすためにのみ使用できます。また、デフォルトのパイプ容量を上書きするには、ダウンストリームコマンドをウェイクアップする必要があります。 fcntlは、私が知る限り、_cmd1_または_cmd2_の内部からのみ呼び出すことができます。

私の質問は、シェルがパイプを作成するときに、パイプに必要な容量をシェルで指定する方法はありますか?

7
CAFxX

DepressedDanielとStéphaneChazelasの提案に基づいて、私が見つけたワンライナーに最も近いものに落ち着きました。

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

これにより、次のことが可能になります。

hugepipe <command> | <command>

2つのコマンド間のパイプは、Perlスクリプトのfcntlを介して指定された容量になります。

1
CAFxX

デフォルトのパイプ容量を超えて書き込む場合でも、ダウンストリームコマンドをウェイクアップする必要があります

ダウンストリームコマンドを頻繁にウェイクアップしないことが目標である場合、-pオプションをbufferに使用してみましたか?バッファが特定のパーセンテージまでいっぱいになるまで、bufferが書き込みを保持するようにする必要があります。大きなチャンクを書き込むには、-sオプションも必要になる場合があります。

更新:D'oh、コマンド間のパイプはまだ物事を制限します。たぶん、次のアダプタプログラムを使用してみてください。

#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がまだ小さな書き込みを行う場合。

4
DepressedDaniel