본문 바로가기

Network/중급 TCP/IP socket

05. pipe() 파이프

멀티 프로세스 이용시 문제점
: 프로세스는 메모리가 독립적으로 존재하기 때문에 메모리를 프로세스간 프로세스간 데이터를 주고 받는 것은 불가능합니다. 쉽게 설명하자면 fork()이용 하여 server 혹은 client 쪽에서 생성된 부모 자식 프로세스 들은 프로그램내 프로세스끼리는 데이터를 주고 받을 방법이 없습니다.

해결책
: 서로 독립된 프로세스들이 데이터를 주고 받기 위해 운영체제는 '파이프'라는 함수를 제공하고 있습니다

pipe() 파이프 생성 함수
-하나의 파이프 및 파이프에 대한 두 개의 파일 디스크립터가 생성
-하나의 파이프를 프로세스들이 공유

#include <unistd.h>
 int pipe(int fd[2]);
성공시 0, 실패시 -1 리턴

-fd : 크기가 2인 int형 배열을 요구
-fd[0] : 함수 호출 후 fd[0]에 데이터를 입력 받을 수 있는 파일 디스크립터가 담김(파이프출구)
-fd[1] : 함수 호출 후 데이터를 출력할 수 있는 파일 디스크립터가 담김(파이프 입구)

 


간단하게 사용해보도록 하겠습니다

pipe1.c 프로그램 작성 예제

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFSIZE 30

int main(int argc, char *argv[])
{
  int fd[2];
  char buffer[BUFSIZE];
  pid_t pid;
  int state;

  state = pipe(fd);
  if(state == -1)
  {
    puts("pipe() error");
    exit(1);
  }

  pid = fork();

  if(pid == -1)
  {
    puts("fork() error");
    exit(1);
  }
  else if(pid == 0)
  {
    write(fd[1], "연결성공!!\n"25);
  }
  else
  {
    read(fd[0],buffer, BUFSIZE);
    puts(buffer);
  }
  return 0;
}

결과>>

pipe1.c의 동작은 아래 그림과 같습니다. 자식프로세스에서 fd[1]으로 write를 하게되면 부모 프로세스에서 fd[0]으로 read를 받아 buffer에 저장하게 됩니다


파이프의 특징
-파이프 자체는 fork함수에 의해 복사되지 않습니다
-파이프는 방향성이 존재하지 않습니다

 



그러면 이번에는 자식에서 write를 해서 부모에서 read하고 다시 write해서 자식프로세서에서 read하는 프로그램을 작성하겠습니다 위의 특징과 비교하여 설명하자면 pipe함수는 fork함수에 의해 2개 3개 로 늘어나지 않고 하나만 존재합니다 그리고 출구와 입구가 지정되어 있어써 출구로 데이터가 들어갈수 없습니다 양쪽데이터가 왔다 갔다 하는 방향성이 존재하지 않습니다

pipe2.c 프로그램 작성예제
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFSIZE 30

int main(int argc, char *argv[])
{
  int fd[2];
  char buffer[BUFSIZE];
  pid_t pid;
  int state;

  state = pipe(fd);
  if(state == -1)
  {
    puts("pipe() error");
    exit(1);
  }

  pid = fork();

  if(pid == -1)
  {
    puts("fork() error");
    exit(1);
  }
  else if(pid == 0)
  {
    write(fd[1], "연결성공!!\n"25);
    sleep(2);
    read(fd[0], buffer, BUFSIZE);
    printf("Output of child process : %s \n\n", buffer);
  }
  else
  {
    read(fd[0],buffer, BUFSIZE);
    printf("Output of parent process : %s \n\n", buffer);
    write(fd[1], "정말 좋아!!"25);
    sleep(2);
  }
  return 0;
}


결과>>


참고>>
위의 프로그램에서 sleep을 해준이유는 write하고 read하기까지 딜레이를 주기위해서 입니다 sleep 없으면 컴퓨터는 대단히 빨리 처리하게되어 파이프로 가기도전에 해당프로세스에서 wrire read를 한번에 처리해 버리게됩니다!

양방향통신을 윈한 파이프 생성
-하나의 파이프를 하나의 용도로 사용하도록 합니다
 : A프로세스에서 B프로세스로 데이터를 전송하기 위한 파이프 하나
 : B프로세스에서 A프로세스로 데이터를 전송하기 위한 파이프 하나


pipe3.c 프로그램 작성 예제
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFSIZE 30

int main(int argc, char *argv[])
{
  int fd1[2], fd2[2];
  char buffer[BUFSIZE];
  pid_t pid;
  
  if(pipe(fd1) == -1||pipe(fd2) == -1)
  {
    puts("pipe() error");
    exit(1);
  }

  pid = fork();

  if(pid == -1)
  {
    puts("fork() error");
    exit(1);
  }
  else if(pid == 0)
  {
    write(fd1[1], "연결성공!!\n"25);
    read(fd2[0], buffer, BUFSIZE);
    printf("Output of child process : %s \n\n", buffer);
  }
  else
  {
    read(fd1[0],buffer, BUFSIZE);
    printf("Output of parent process : %s \n\n", buffer);
    write(fd2[1], "정말 좋아!!"25);
    sleep(1);
  }
  return 0;
}


결과>>