다음을 사용하여 파일 설명자를 만들었습니다.
mkfifo fifo
이 파이프에 뭔가가 쓰여지면 재사용하고 싶습니다.곧. 내가 사용해야 할까?
tail -f fifo
또는
while true; do cat fifo; done
?
그들은 똑같은 일을 하는 것 같고 성능 차이를 측정할 수 없습니다. 그러나 시스템이 inotify(예: Busybox)를 지원하지 않는 경우 전자를 다음으로 설정해야 합니다.
tail -f -s 0 fifo
mkfifo fifo && busybox tail -f -s 0 fifo & echo hi>fifo
하지만 이 작업은 CPU 사용량이 100%입니다( /cancel fg 1
및 으로 테스트 CtrlC). 그렇다면 while-true-cat이 더 안정적인 솔루션일까요?
답변1
이 작업을 수행할 때:
cat fifo
fifo
이미 쓰기 위해 열려 있는 다른 프로세스가 없다고 가정하면 시스템 호출이 cat
차단됩니다 open()
. 다른 프로세스가 쓰기 위해 파일을 열면 파이프가 인스턴스화되어 open()
반환됩니다. 루프가 호출되어 다른 프로세스가 파이프에 데이터를 쓸 때까지 차단 cat
됩니다 .read()
read()
cat
파일 끝(eof) 문자는 다른 모든 쓰기 프로세스가 파일 설명자를 닫았을 때 표시됩니다 fifo
. 이것이 cat
종료되고 파이프라인이 파괴됩니다.
cat
나중에 작성된 내용을 읽으려면 다시 실행 해야 합니다 fifo
(그러나 다른 파이프 인스턴스를 통해).
존재하다:
tail -f file
마찬가지로 프로세스가 쓰기 위해 파일을 열 때까지 기다립니다 cat
. 그런데 여기서는 처음부터 복사를 tail
지정하지 않았기 때문에 마지막 10줄이 무엇인지 알아내려면 eof까지 기다려야 하기 때문에 쓰기가 끝날 때까지 아무 것도 보이지 않습니다.-n +1
tail
그 후에 tail
해당 fd는 파이프에 대해 닫히지 않습니다. 이는 파이프 인스턴스가 파괴되지 않고 여전히 매초 파이프에서 읽으려고 시도한다는 것을 의미합니다(Linux에서는 inotify
일부 버전의 GNU를 사용하여 폴링을 방지 할 수 있습니다 tail
). 이는 다른 프로세스가 다시 쓰기 위해 파일을 열 때까지 eof(즉시 100% CPU가 표시되는 이유입니다 (GNU의 경우 1초를 기다리는 대신 s 사이를 기다리지 않음을 의미함 )) read()
를 반환합니다 .-s 0
tail
read()
대신 여기에서 를 사용하고 싶을 수도 있지만 cat
인스턴스화 후에 파이프 인스턴스가 항상 근처에 남아 있는지 확인하세요. 이렇게 하려면 대부분의 시스템에서 다음을 수행할 수 있습니다.
cat 0<> fifo # the 0 is needed for recent versions of ksh93 where the
# default fd changed from 0 to 1 for the <> operator
cat
stdin은 읽기 및 쓰기를 위해 열려 있습니다. 즉, cat
eof는 결코 표시되지 않습니다( fifo
다른 프로세스가 쓰기를 위해 파이프를 열지 않더라도 즉시 파이프를 인스턴스화합니다).
이것이 작동하지 않는 시스템에서는 다음을 수행할 수 있습니다.
cat < fifo 3> fifo
이렇게 하면 다른 프로세스가 fifo
쓰기 위해 열리면 첫 번째 읽기 전용이 open()
반환되며, 이 시점에서 셸은 open()
시작하기 전에 쓰기 전용을 수행 cat
하여 파이프가 다시 끊어지는 것을 방지합니다.
요약하면 다음과 같습니다.
- 대조적으로
cat file
, 첫 번째 라운드 이후에는 멈추지 않습니다. - 비교하자면
tail -n +1 -f file
: 첫 번째 라운드 후에는read()
매초마다 쓸모없는 작업을 수행하지 않으며 파이프의 한 인스턴스에는 eof가 없으며 두 번째 프로세스가 쓰기 위해 파이프를 열지 않은 후에는 지연이 있습니다. 최대 1초. 첫 번째는 그것을 닫았습니다. - 에 비해
tail -f file
. 위의 내용 외에도 무언가를 출력하기 전에 첫 번째 라운드가 끝날 때까지 기다릴 필요가 없습니다(마지막 10줄만). - 루프와 달리
cat file
파이프 인스턴스는 하나만 있습니다. 1에서 언급한 경합 창은 방지됩니다.
read()
1 이 시점에서 eof의 마지막 표현과 cat
파이프의 읽기 끝이 종료되고 닫히는 시간 사이에는 실제로 프로세스가 fifo
쓰기를 위해 파이프를 다시 열 수 있는 작은 창이 있습니다. 아직 읽은 내용이 있습니다. Take the end). 그런 cat
다음 종료 후 다른 프로세스가 읽기 프로세스를 열기 전에 fifo
무언가를 쓰면 SIGPIPE에 의해 종료됩니다.
답변2
다른 해결책을 제안하겠습니다. 두 번째 끝에 쓰는 프로세스가 있는 한 파이프를 읽을 수 있습니다. 따라서 cat
백그라운드(또는 다른 터미널)에서 가짜를 만들 수 있습니다. 예를 들면 다음과 같습니다.
mkfifo fifo
cat >fifo &
cat fifo
이제 필요에 따라 fifo에 쓸 수 있으며 완료되면 현재 프로세스 종료를 사용한 cat
다음 C-c먼저 백그라운드에서 시작 fg
하고 마지막으로 중지합니다.cat
C-d