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

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

이제 명명된 파이프를 읽고 있는지 확인하기 위한 형편없는 검사가 있습니다.

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에 의해 종료되고 SIGPIPE0이 아닌 상태를 반환합니다.

내장 함수는 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 경로는 위 프로그램에 하드코딩되어 있습니다.

관련 정보