연결되지 않은 상태에서 파이프가 삭제되면 명명된 파이프 블록을 영구적으로 엽니다.

연결되지 않은 상태에서 파이프가 삭제되면 명명된 파이프 블록을 영구적으로 엽니다.

다음 쉘 명령을 시도해 보십시오.

mkfifo /tmp/test.pipe

ls -1 /tmp > /tmp/test.pipe &

rm /tmp/test.pipe
mkfifo /tmp/test.pipe
cat /tmp/test.pipe &

jobs

ls명령은 단지 예일 뿐이며 명명된 파이프에 쓰려는 모든 프로세스가 될 수 있습니다. 여기서 중요한 점은 프로세스가 쓰기를 위해 파이프를 열려는 시도를 차단한다는 것입니다. 이제 또 다른 프로세스가 나타나 파이프를 제거합니다. 동일한 이름을 가진 새 파이프가 생성되고 cat프로세스(즉, 읽기 위해 열려고 시도하는 모든 프로세스)는 다른 프로세스가 동일한 이름을 가진 새 파이프에 쓸 때까지 기다리는 것을 차단합니다. 두 프로세스 모두 각각의 파이프 연결을 기다리고 있습니다. 이는 배경을 나열하여 확인할 수 있습니다 jobs.

cat파이프에서 실제로 읽는 프로세스는 실제로 파이프를 대체한 프로세스이기 때문에 차단(또는 파이프에서 읽으려는 프로세스)에 대해 크게 걱정하지 않습니다 . 사실 나는 읽는 과정에 전혀 관심이 없습니다. 유일한 cat예는 두 프로세스가 동일한 파이프 파일 이름을 참조하지만 분명히 다른 파이프 인스턴스를 사용한다는 증거입니다. 그러나 이 교착 상태 예제는 반대의 경우에도 차단됩니다. 즉, 쓰기를 위해 열지 않고 파이프를 삭제하면 읽기 프로세스가 영원히 차단됩니다.

내 초점은 쓰기 프로세스를 차단하는 것입니다( ls내 예에서는). 쓰려고 했던 원래 파이프가 같은 이름을 가진 새 파이프로 대체되었다는 사실을 결코 깨닫지 못합니다.

프로세스가 더 이상 존재하지 않는 명명된 파이프에 대한 쓰기 액세스를 차단하는 상황을 Linux에서 식별할 수 있는 방법이 있습니까?당신은 루트 권한을 가질 수 있으며 관련된 모든 프로세스의 PID를 알고 있습니다. 특히 글쓰기 과정에서는 이것이 사실일 수도 있고 아닐 수도 있다는 것을 알고 있기 때문에 더욱 그렇습니다. 하지만 모르겠어요 (그건궁금합니다) 만약 이 과정에서 실제로 이런 문제가 발생한다면, 종료할 수 있습니다.파일 시스템에 더 이상 물리적으로 존재하지 않는 명명된 파이프에 대한 액세스를 차단하는 프로세스를 어떻게 찾을 수 있습니까?

분명히, ls /proc/<PID>/fd두 프로세스 중 하나의 파이프에 액세스하기 위한 파일 설명자는 파이프의 양쪽 끝이 연결되지 않는 한 나열되지 않습니다. 즉, ls /proc/<PID>/fd두 프로세스의 파이프에 대한 파일은 시스템 호출이 두 프로세스 설명자 끝으로 성공적으로 반환된 후에만 나열됩니다. . 내 경우에는 두 가지가 다르기 때문에반연결파이프 이름은 동일하지만 프로세스가 모두 나열되지 않습니다.

답변1

제안대로줄리 펠레티에, 저는 토론에서 찾은 해결책에 대해 이 답변을 드립니다.

내 질문에 설명된 교착상태 상황을 쉽게 식별할 수는 없지만 선제적으로 대처할 수는 있습니다.벤트누군가가 삭제하기 전에 해결 방법으로 명명된 파이프입니다(제 경우처럼 삭제를 피할 수 없는 경우). 이러한 환기를 통해 현재 파이프를 열려고 시도하는 것이 차단된 모든 기록기가 작업을 성공적으로 열 수 있지만 실제 쓰기 작업 중에는 실패할 수 있습니다(-> 손상된 파이프). 갇히는 것보다 실패하는 것이 더 나을 수도 있습니다. 곧바로 다음 교착 상태에 빠지지 않으려면 환기하기 전에 파이프를 이동한 후 제거해야 합니다.

# rename the pipe, i.e. move it out of the way
mv -f /tmp/test.pipe /tmp/test.pipe~ 2>/dev/null

# vent the pipe, i.e. shortly open it for reading but don't read from it.
# call the subshell dd and empty echo calls in the background to avoid 
# deadlocking on redundant venting.
(dd if=/tmp/test.pipe~ count=0 2>/dev/null & echo -n "" >/tmp/test.pipe~ &)

# delete the old pipe
rm -f /tmp/test.pipe~

어떤 프로그램이 잘못된 삭제를 수행했는지 알고 있는 경우 해당 프로그램을 삭제를 취소하고 중단하는 작은 스크립트로 래핑할 수 있습니다.

관련 정보