리눅스 pipe 함수 : 파이프를 만든다

OS/리눅스 2020. 6. 14. 01:38

 안녕하세요. 이번 시간에는 리눅스 pipe 함수에 대해서 알아보도록 하겠습니다.

 

 

 file 데스크립터 2개를 저장할 배열을 넘겨주기만 하면 됩니다. 그것을 넘겨주면, 그 배열에 하나는 파이프에서 읽기를, 하나는 쓰기를 할 수 있는 데스크립터가 생성됩니다. 각각 filedes[0], filedes[1]이 그 역할을 합니다.

 


 예제 1번 프로그램을 보도록 하겠습니다.

 

 먼저, text가 2개 있습니다. 하나는 "Hello", 하나는 "Bye" 입니다. 파이프를 생성한 다음에, fork로 자식 프로세스를 생성합니다.

 

 

 상황이 대략적으로 이렇게 그려집니다.

 

 

 그리고 부모에서는, 단순하게 "Hello"라는 text를 write 하기만 하고, 자식은 받기만 합니다. 일단, 자식의 pi[0]과 부모의 pi[0], 그리고 자식의 pi[1]과 부모의 pi[1]은 같은 디스크립터인데요. pi[0], pi[1]은 r만 되냐, w만 되냐의 차이일뿐, 사실 같은 파이프와 관련된 무언가입니다.

 

 그러면, 파이프에 "Hello" 라는 것을 부모가 write를 할 겁니다.

 

 

 그리고 자식이 파이프에 쓰여진 "Hello"라는 것을 읽어갈 겁니다.

 

 

 

 프로그램의 실행 결과는 위와 같습니다. 그런데, 사실 자식 프로세스와 부모 프로세스 중에 누가 먼저 수행되는지는 잘 모릅니다. 때에 따라서는 자식이, 아니면 그 반대의 경우가 먼저일 수도 있습니다.

 


 그러면 부모와 자식이 서로 파이프로 데이터를 주고 받아야 하는 경우에는 어떻게 해야 할까요?

 

 

 비슷해 보입니다. 일단, 저는 parent는 "bye"를 보낼 거고, child는 "Hello"를 보낼 겁니다. 그리고 parent가 보낸 것은 자식이 읽고, 자식이 보낸 것은 부모가 읽게끔 하겠습니다.

 

 

 부모 프로세스가 수행하는 코드입니다.

 

 

 그리고 이것은 자식 프로세스가 수행하는 코드입니다. 실행 결과가 어떻게 나올까요?

 

 

 한 번 돌려보니 이렇게 나왔습니다. parent : Hello가 먼저 출력되었고, 그 다음에 CHILD가 출력되더니, 값을 받아오지 못합니다. 일단 parent : HELLO가 출력되었다는 이야기는 부모 자신이 text[0]을 쓰고, 그것을 부모 자신이 읽었다는 의미입니다.

 

 

 대충 이런 상황입니다. 그리고 parent : HELLO가 출력된 시점에서, 파이프에는 아무것도 남아있지 않습니다.

 

 

 이 상태로 파이프에서 읽어내려고 한다면 어떻게 될까요? 링크를 보시면, 중간에 이런 문구가 있습니다.

 

 

 결국 핵심은, empty pipe를 읽으려고 할 때, 데이터가 available 될 때 까지 block이 걸린다는 것인데요. 이미 "Hello" 라는 것을 부모가 가져가 버렸으니, 자식은 데이터를 읽을 때 까지 계속 대기를 할 겁니다. 그러다가 끝날 겁니다. 물론 정말 운이 좋게, parent가 문자열 "Hello"를 write 하자마자 child가 그것을 읽고 "bye"를 보내서, parent가 그것을 읽는 시나리오가 나올 수도 있을 겁니다. 그러면 의도대로 실행된 것일 겁니다.

 

 그런데, 어떤 순서대로 수행이 될 지는 잘 모릅니다. 부모가 자기가 쓴 걸 자기가 읽는 시나리오가 나올 수도 있을 겁니다. 이는 파이프 하나에 부모가 "Hello"라는 것을 썼을 때, 자식과 부모 둘 중 하나가 read를 할 수 있기 때문입니다. 한 파이프에 2개의 프로세스가, 값을 가져가기 위해 '경쟁'을 하고 있는 셈입니다. 이 문제를 피하기 위해서, 파이프 2개를 생성해서 하나는 자식이 보낸 것을 부모가 받게끔 하고, 다른 하나는 부모가 보낸 것을 자식이 받게끔 하면 됩니다.