유닉스 / 리눅스에서의 파이프 명령 이해 가져 와서 A”stdin”으로

나는 두 가지 간단한 프로그램을 가지고 AB. A먼저 실행 한 다음 B“stdout” 을 가져 와서 A“stdin”으로 사용합니다. GNU / Linux 운영 체제를 사용하고 있으며 가장 간단한 방법은 다음과 같습니다.

./A | ./B

이 명령을 설명해야한다면,이 명령은 생산자 ( A) 로부터 입력 (즉, 읽기)을 받아서 소비자 ( B) 에게 쓰는 명령이라고 말할 수 있습니다 . 이것이 올바른 설명입니까? 아무것도 빠졌습니까?



답변

귀하의 질문에 대해 잘못 된 유일한 것은 당신이 말하는 것입니다.

A가 먼저 실행되면 B는 A의 표준을 얻습니다.

실제로 두 프로그램은 거의 동시에 시작됩니다. B읽을 때 입력이 없으면 읽을 입력이있을 때까지 차단됩니다. 마찬가지로에서 출력을 읽는 사람이 없으면 A출력을 읽을 때까지 쓰기가 차단됩니다 (일부는 파이프에 의해 버퍼링 됨).

파이프 라인에 참여하는 프로세스를 동기화하는 유일한 것은 I / O, 즉 파이프를 통한 읽기 및 쓰기입니다. 쓰거나 읽지 않으면 두 프로세스가 서로 독립적으로 실행됩니다. 하나가 다른 쪽의 읽기 또는 쓰기를 무시하면 무시 된 프로세스는 차단되고 결국 SIGPIPE다른 프로세스가 종료 될 때 신호에 의해 종료되거나 (쓰기중인 경우) 표준 입력 스트림에서 파일의 끝 조건 (읽기 경우)을 얻습니다. .

관용적 인 설명 A | B은 두 개의 프로그램이 포함 된 파이프 라인이라는 것입니다. 첫 번째 프로그램에서 표준 출력으로 생성 된 출력은 두 번째로 표준 입력에서 읽을 수 있습니다 ( “[출력] A은 [입력] B” 으로 파이프됩니다 ). 쉘은이를 위해 필요한 배관 작업을 수행합니다.

“소비자”와 “제작자”라는 단어를 사용하려면 괜찮다고 생각합니다.

이것들이 C로 작성된 프로그램이라는 사실은 관련이 없습니다. 이것이 Linux, macOS, OpenBSD 또는 AIX라는 사실은 관련이 없습니다.


답변

문서에서 일반적으로 사용되는 용어는 하나 이상의 명령으로 구성된 “파이프 라인”입니다. POSIX 정의를 참조하십시오. 기술적으로 말하자면, 여기에는 두 개의 명령, 쉘에 대한 두 개의 하위 프로세스 ( fork()+exec()‘ed external 명령 또는 서브 쉘’)가 있습니다.

생산자-소비자 부분에 대해서는 다음과 같은 이유로 파이프 라인을 해당 패턴으로 설명 할 수 있습니다.

  • 생산자와 소비자는 고정 크기 버퍼를 공유하며, 적어도 Linux 및 MacOS X에서는 파이프 라인 버퍼고정 크기가 있습니다.
  • 생산자와 소비자는 느슨하게 연결되어 있으며 파이프 라인의 명령은 서로의 존재를 알지 못합니다 ( /proc/<pid>/fd디렉토리를 적극적으로 확인하지 않는 한 ).
  • 생산자 들은 마치 하나의 명령이 실행되는 것처럼 stdout읽고 쓰며 소비자 stdin서로없이 존재할 수 있습니다 .

내가 보는 차이점은 다른 언어의 Producer-Consumer와 달리 셸 명령은 버퍼링을 사용하고 버퍼가 채워지면 stdout을 작성하지만 Producer-Consumer는 해당 규칙을 따라야한다는 언급은 없습니다. 대기열이 채워지거나 버릴 때만 기다리십시오 데이터 (파이프 라인이하지 않는 다른 것).