지금은 다음에서 명명된 파이프를 읽고 있는지 알아보기 위한 형편없는 검사가 있습니다.
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/echo
a에 의해 종료되고 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 경로는 위 프로그램에 하드코딩되어 있습니다.