유닉스 / 리눅스에서의 파이프 명령 이해


16

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

./A | ./B

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



그것은 명령이 아니며 bash 프로세스에 의해 생성 된 kenerl 객체입니다.이 프로세스는 프로세스 A의 stdout으로 사용되고 stdin은 B로 사용됩니다. 두 프로세스가 거의 동시에 시작됩니다.
炸鱼 薯条 德里克

1
커널 파이프 라인은 pipefs 파일 시스템의 객체이지만 쉘 자체는 기술적으로는 파이프 라인 명령입니다
Sergiy Kolodyazhnyy

답변:


26

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

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

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

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

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

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

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


2
DOS에서는 임시 파일에 쓰는 것이 여러 프로세스를 지원하지 않기 때문에 사용되었습니다.
CSM

2
@AlexVong 임시 파일이있는 예제는 정확히 동일하지는 않습니다. 프로그램은 파일의 내용을 통해 검색을 선택할 수 있지만 파이프에서 나오는 데이터는 검색 할 수 없습니다. 더 나은 examlp는 mkfifo명명 된 파이프를 만드는 데 사용 하고 파이프에서 백그라운드 읽기에서 B를 시작한 다음 A를 쓰는 것입니다. 그러나 효과 는 동일 하므로 nit-picking 입니다.
Kusalananda

2
@AlexVong이 기사에서 만든 단순화는 실제 파이프 라인과 이혼한다. 병렬 실행은 최적화가 아니라 실제로 의미 론적입니다. 쉘 파이프 라인을 본 사람에게는 모나드 평가 또는 구성에 대한 합리적인 거짓말-어린이 설명 이지만 다른 방향으로는 유효하지 않습니다. Kusalananda의 fifo 버전은 더 가깝지만 모델의 오류 전파 부분은 실제로 중요하며 복제 할 수 없습니다. (모두 "쉘 파이프 라인은 단지 기능 구성"기차에있는 누군가라고 말합니다.)
Michael Homer

6
@AlexVong 아니오, 그것은 완전히 벗어났습니다. 그와 같은 경우에도 뭔가 간단한 설명 할 수 없습니다 yes | sed 10q
삼촌 빌리

1
@ UncleBilly 나는 당신의 예에 동의합니다. 이것은 병렬 실행이 실제로 Michael에게도 필요하다는 것을 보여줍니다. 그렇지 않으면, 우리는 종료되지 않습니다.
Alex Vong

2

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

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

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

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.