名前付きパイプが読み取り用に開いていることを確認する

名前付きパイプが読み取り用に開いていることを確認する

今、名前付きパイプを読んでいることを確認するための不都合なチェックがあります。

is_named_pipe_being_read() {

    local named_pipe="$1" 
    echo "unlocked" > "$named_pipe" & 
    pid="$!"
    # Wait a short amount of time
    sleep 0.25
    # Kill the background process. If kill succeeds, then
    # the write was blocked 
    ( kill -PIPE "$pid" ) &> /dev/null
}

シャットダウンが有効な場合(0で終了)、パイプから読者がいないことを意味します。

しかし、0.25秒の遅延を持って不要なプロセスを開始するのではなく、名前付きパイプが読み取り用に開いていることを確認する方法を探しています。何かが読まれているかどうかを確認する方法はありますか?

ノート: この呼び出しでは、パイプからデータを読み取ることができず、書き込みのみできます。 (名前付きパイプを使用すると、リーダーの接続順序が尊重されないようですから、または最新のデータを取得したリーダーがそうかもしれません。)、最も古い読者ではありません)。

答え1

if /bin/echo unlocked 1<>fifo >fifo; then
    there are readers
else
    no there ain\'t
fi

is_named_pipe_being_read(){ /bin/echo unlocked 1<>"$1" >"$1"; }

リーダーがない場合は/bin/echoa で終了し、SIGPIPEゼロ以外の状態を返します。

組み込み関数はecho(サブシェルでも)使用できませんSIGPIPE。シェル全体が閉じ込められたり終了したりするからです。

OPバージョンと同様に、これは破壊的です。 GNU ddがある場合は、次のようにファイルを開くことができますO_NONBLOCKC

is_named_pipe_being_read(){ dd oflag=nonblock conv=notrunc,nocreat count=0 of="$1" 2>/dev/null; }

ただし、パイプに別の作成者がいる場合、コマンドの終了時に自動的にfifoを閉じると、すべてのリーダーがEOFを受け取ります。

メモ:名前付きパイプの使用は、マゾヒズムや標準的な玄関行為に近い[1]。 Unix ドメインソケットによって実装された BSD ソケット API は比較的に優れているので(これが世界を支配する理由です;-)、netcatシェルでもこれを使用できるようにするプログラム(最新バージョンのような)があります。

[1]は上記の例で敗北したこれ実際、rwモードでfifoを開くのは標準に従って「未定義」です。しかし、同じ慣行が約30年前からほとんどのシステムで実装されました。

答え2

私はここからこのCプログラムを盗みました。https://stackoverflow.com/a/20694422/5047085:

#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<stdlib.h>
#include <sys/stat.h>

#define SERVFIFO "/Users/alex/.locking/ql/locks/a/fifo.lock"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

void syserr(const char *str){
    perror(str);
    exit(1);
}

int main(int argc, char** argv){

    umask(0);

    // try to open for write with no readers

    int fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);

    if (fdw == -1){
      syserr("non-blocking open for write with no readers failed");
    }

    // create a reader - the process itself - non-blocking

    int fdr = open(SERVFIFO, O_RDONLY | O_NONBLOCK);
    if (fdr == -1){
      syserr("non-blocking open for read no writers failed");
    }

    // try again to open for write but this time with a reader
    fdw = open(SERVFIFO, O_WRONLY | O_NONBLOCK);

    if (fdw == -1){
      syserr("non-blocking open with readers failed");
    }


    printf("non-blocking open for write succeeded\n");

    close(fdw);
    close(fdr);

}

ゼロで終わると、誰かがすでに名前付きパイプで読んでいるという意味ですか? 1で終わると誰も読まないという意味です。

これは間違っているかもしれませんが、基本的なテストではうまくいくようです。 FIFOパスは上記のプログラムにハードコードされています。

関連情報