명명된 파이프가 읽기 위해 열려 있는지 확인

명명된 파이프가 읽기 위해 열려 있는지 확인

지금은 다음에서 명명된 파이프를 읽고 있는지 알아보기 위한 형편없는 검사가 있습니다.

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
}

kill이 작동하면(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에 의해 종료되고 0 이 아닌 상태를 반환합니다.SIGPIPE

내장된 기능은 echo(하위 쉘에서도) 사용할 수 없습니다 SIGPIPE. 전체 쉘이 포착되거나 종료되기 때문입니다.

OP의 버전과 마찬가지로 이것은 파괴적입니다. GNU dd가 있는 경우 O_NONBLOCK다음과 같이 를 사용하여 파일을 열어볼 수 있습니다 C.

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

그러나 이것은 그다지 좋지 않습니다. 파이프에 다른 작성자가 있는 경우 명령 종료 시 fifo가 자동으로 닫히면 모든 판독기가 EOF를 받게 됩니다.

메모:명명된 파이프를 사용하는 것은 마조히즘이나 표준 현학의 문제에 가깝습니다 [1]. 유닉스 도메인 소켓에 의해 구현된 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);

}

0으로 종료된다면 누군가가 이미 명명된 파이프에서 읽고 있다는 의미입니까? 그리고 1로 종료되면 아무도 읽지 않는다는 의미입니다.

이는 잘못된 것일 수 있지만 기본 테스트에서는 작동하는 것으로 나타났습니다. FIFO 경로는 위 프로그램에 하드코딩되어 있습니다.

관련 정보