명명되지 않은 파이프를 생성할 때 두 개의 파일 설명자가 필요한 이유는 무엇입니까?

명명되지 않은 파이프를 생성할 때 두 개의 파일 설명자가 필요한 이유는 무엇입니까?

나는 명명되지 않은 파이프에 대해 읽었으며 내가 이해한 바에 따르면 파이프는 메모리의 버퍼로 구현됩니다. 파이프를 생성할 때 버퍼(파일 설명자)에 대한 두 개의 포인터를 반환하는 크기 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가 하나만 있고 grephead다 상속된 경우 grep종료할 때 headEOF를 받아야 합니다 . 그러나 프로세스가 보유한 fd head는 쓰기 가능하므로 커널은 파이프에 더 이상 쓸 것인지 확실하지 않습니다. 프로세스 종료는 프로세스가 보유한 모든 파이프 fd에 자동으로 EOF를 보내야 한다고 생각할 수도 있습니다. 그러나 이것은 다음과 같은 많은 것을 깨뜨릴 것입니다.

( echo FOO ; grep foo /etc/passwd ) | more

echo파이프에 쓰고 종료합니다. 아직 EOF가 발생하는 것을 원하지 않습니다. grep여전히 파이프에 쓸 것입니다. 이 문제는 괄호 안에 있는 하위 쉘의 "모호한" 경우에만 국한되지 않습니다. 이는 파이프 왼쪽에서 쉘 스크립트를 사용할 때마다 발생할 수 있습니다.

생각해 보면 파이프 EOF 메커니즘은 파이프에 쓸 수 있는 fd와 파이프에서만 읽을 수 있는 fd를 구별해야 합니다. 관련된 프로세스 수에 따라 달라지지 않습니다.

관련 정보