두 가지 간단한 프로그램이 있습니다: A
및 B
. A
먼저 실행한 다음 B
"stdout"을 가져와 A
"stdin"으로 사용합니다. GNU/Linux 운영 체제를 사용한다고 가정하면 가장 간단한 방법은 다음과 같습니다.
./A | ./B
이 명령을 설명해야 한다면 A
생산자()로부터 입력(읽기)을 받고 소비자( )에 쓰는 B
명령 이라고 말하고 싶습니다. 이것이 올바른 설명인가요? 내가 뭐 놓친 거 없니?
답변1
귀하의 질문에서 눈에 띄는 유일한 점은잘못된당신 말이 맞아요
A가 먼저 실행되고 B가 A의 표준 출력을 얻습니다.
사실 두 프로그램은 거의 동시에 시작됐다. 읽으려고 할 때 입력이 없으면 B
읽을 입력이 있을 때까지 차단됩니다. 마찬가지로, 아무도 출력을 읽지 않으면 A
출력을 읽을 때까지 쓰기가 차단됩니다(일부는 파이프에 의해 버퍼링됨).
파이프라인에 참여하는 프로세스를 동기화하는 유일한 것은 I/O, 즉 파이프라인 전체에서 읽고 쓰는 것입니다. 쓰기나 읽기가 발생하지 않으면 두 프로세스는 완전히 독립적으로 실행됩니다. 한 프로세스가 다른 프로세스의 읽기 또는 쓰기를 무시하면 무시된 프로세스는 차단되어 결국 신호 SIGPIPE
(쓰기의 경우)에 의해 종료되거나 다른 프로세스가 조건( 읽는다면).
이를 관용적으로 표현하면 A | B
두 개의 프로그램을 포함하는 파이프라인이라는 것입니다. 표준 출력의 첫 번째 프로그램에서 생성된 출력은 표준 입력의 두 번째 프로그램에서 읽을 수 있습니다("[의 출력]은 A
[의 입력]으로 파이프됩니다 B
"). 쉘은 이를 달성하기 위해 필요한 파이프 작업을 수행합니다.
'소비자', '생산자'라는 단어를 사용하고 싶다면 그것도 괜찮을 것 같아요.
이것이 C로 작성된 프로그램이라는 사실은 부적합합니다. 이것이 Linux, macOS, OpenBSD 또는 AIX라는 사실은 부적합합니다.
답변2
문서에서 일반적으로 사용되는 용어는 하나 이상의 명령으로 구성된 "파이프라인"입니다.POSIX 정의 보기fork()+exec()
따라서 기술적으로는 두 개의 명령, 두 개의 셸 하위 프로세스( "외부 명령 사용" 또는 "하위 쉘") 입니다.
에 관해서는생산자-소비자부분적으로 파이프라인은 다음과 같은 이유로 이 패턴으로 설명될 수 있습니다.
- 생산자와 소비자는 적어도 Linux 및 MacOS X에서는 고정 크기 버퍼를 공유합니다.파이프 버퍼의 고정 크기
/proc/<pid>/fd
생산자와 소비자는 느슨하게 결합되어 있으며 파이프라인의 명령은 디렉터리를 적극적으로 확인하지 않는 한 서로의 존재를 인식하지 못합니다 .- 생산자 쓰기 및 소비자 읽기는 실행되는 단일 명령인 것처럼
stdout
기록됩니다 .stdin
서로 없이도 존재할 수 있다.
여기서 볼 수 있는 차이점은 다른 언어의 생산자-소비자와 달리 쉘 명령은 버퍼링을 사용하고 버퍼가 가득 차면 stdout에 기록하지만 생산자-소비자가 해당 규칙을 따라야 한다는 언급은 없다는 것입니다. 큐가 가득 차거나 삭제될 때의 데이터(파이프가 수행하지 않는 다른 작업)