나는 명명되지 않은 파이프에 대해 읽었으며 내가 이해한 바에 따르면 파이프는 메모리의 버퍼로 구현됩니다. 파이프를 생성할 때 버퍼(파일 설명자)에 대한 두 개의 포인터를 반환하는 크기 2의 배열을 전달해야 합니다. 인덱스 0은 파이프에서 읽는 데 사용되고 인덱스 1은 쓰기에 사용됩니다.
내 질문은 버퍼가 하나만 있고 두 인덱스가 모두 동일한 메모리 위치를 가리키고 두 프로세스가 동시에 읽고 쓸 수 없는 경우 두 개의 파일 설명자가 필요한 이유는 무엇입니까? 내 질문이 의미가 있기를 바랍니다.
답변1
@MelBoyce가 그의 의견에서 언급했듯이 이는 파이프의 개념적 특성 때문입니다. 여기에는 입력과 출력이 있으며 입력에 기록된 순서와 정확히 동일한 순서로 출력에서 바이트를 읽습니다. 파이프는 일반적인 파일이나 포인터가 아니므로 파이프 안의 어느 곳에서도 읽거나 쓸 수 없습니다. 파이프로 들어오는 읽지 않은 첫 번째 바이트를 강제로 읽어야 합니다.
파이프는 메모리의 버퍼로 구현될 수 있지만 향후 더 효율적인 다른 방법이 개발되면 구현이 달라질 수 있습니다. 그러나 파이프라인의 개념적 특성은 변경되지 않습니다. 여전히 동일한 시스템 호출을 사용 read(2)
하고 write(2)
동일하게 작동합니다. 호출 시 얻은 파일 설명 pipe(2)
자는 파이프를 올바르게 사용하도록 강제하는 데 사용됩니다(추가로 일부 액세스 제어 제공). 이렇게 하면 향후 구현 수정으로 인해 코드가 손상되지 않습니다.
답변2
읽기 및 쓰기를 위한 단일 파일 설명자가 반환된 경우 중요한 기능이 누락됩니다 pipe
. 즉, EOF 신호가 발생하지 않습니다.
파이프의 경우 fd를 읽으면 fd가 기록된 마지막 복사본이 닫힐 때 EOF가 표시됩니다. 가상의 단일 FD 파이프라인의 경우 소켓과 마찬가지로 추가 시스템 호출이 필요 shutdown
하지만 파이프라인에 적용됩니다. (파이프는 소켓보다 오래되었으며 shutdown
소켓 이전에는 존재하지 않았다는 점을 기억하십시오.)
pipe_shutdown()
이 시스템 호출을 호출하는 책임은 누구에게 있습니까 ? 다음과 같이 한다고 가정해 보세요.
grep foo /etc/passwd | head
fd가 하나만 있고 grep
둘 head
다 상속된 경우 grep
종료할 때 head
EOF를 받아야 합니다 . 그러나 프로세스가 보유한 fd head
는 쓰기 가능하므로 커널은 파이프에 더 이상 쓸 것인지 확실하지 않습니다. 프로세스 종료는 프로세스가 보유한 모든 파이프 fd에 자동으로 EOF를 보내야 한다고 생각할 수도 있습니다. 그러나 이것은 다음과 같은 많은 것을 깨뜨릴 것입니다.
( echo FOO ; grep foo /etc/passwd ) | more
echo
파이프에 쓰고 종료합니다. 아직 EOF가 발생하는 것을 원하지 않습니다. grep
여전히 파이프에 쓸 것입니다. 이 문제는 괄호 안에 있는 하위 쉘의 "모호한" 경우에만 국한되지 않습니다. 이는 파이프 왼쪽에서 쉘 스크립트를 사용할 때마다 발생할 수 있습니다.
생각해 보면 파이프 EOF 메커니즘은 파이프에 쓸 수 있는 fd와 파이프에서만 읽을 수 있는 fd를 구별해야 합니다. 관련된 프로세스 수에 따라 달라지지 않습니다.