본문 바로가기
Language/C언어

C055_pipe 함수 사용하기

by OdOp 관리자 2024. 1. 13.
SMALL

시작하기에 앞서서 fork에 대해 아직은 잘 모르시는 분들은 아래의 링크를 참고해 주시길 바랍니다. 

https://hig0617.tistory.com/134

 

파이프는 2가지로 나뉩니다. '이름 없는 파이프', '이름 있는 파이프' 이렇게 2가지로 나뉘게 되는데, 오늘은 '이름 없는 파이프'에 대해 중점적으로 알아보는 시간을 가지도록 하겠습니다. 

 

간단하게 '이름 없는 파이프'와 '이름 있는 파이프'에 대해 알아보도록 하겠습니다. 

 

이름 없는 파이프(PIPE)

이름 없는 파이프는 부모와 자식 프로세스 간에 통신을 할 수 있게 해 줍니다.

다만 한 방향으로 진행이 됩니다. '부모->자식', 혹은 '자식->부모'로 둘 중에 한 방향으로만 진행이 가능합니다. 

 

이름 있는 파이프(FIFO)

이름 있는 파이프는 독립적인 프로세스들이 파이프를 이용하여 통신을 할 수 있습니다. 부모-자식 관계에 국한이 되지 않습니다. 

 

간단하게 두 개의 파이프에 대해 살펴보았습니다.

오늘의 위의 두 개 중에서 '이름 없는 파이프(PIPE)'에 대해 알아보도록 하겠습니다. 

 

PIPE 설명

파이프는 두 프로세스 사이에서 한 방향으로 통신할 수 있도록 진원을 해줍니다. 쉘에서 '|'기호를 의미합니다. 

예시를 한번 본다면 쉽게 이해하실 것이라고 생각이 됩니다. 

ls | wc -l

 

위의 명령어를 실행해 보도록 하겠습니다. 

'ls' 명령에 대한 결과를 'wc -l'에 전달을 하게 됩니다. 

어떻게 보면 파이프(|)를 중심으로 서로 소통을 한다고 볼 수 있습니다. 

 

 

pipe 원리

시작에 앞서서 함수 원형 먼저 살펴보도록 하겠습니다. 

#include <unistd.h>

int	pipe(int fd[2]);

 

인자 값으로 들어온 'fd[2]'는 pipe를 연결해 주는 파일디스크립터입니다.

fd[0] : 파이프에 적힌 내용을 읽습니다. 쉽게 설명을 하면 'O_RDONLY'라고 할 수 있습니다. 

fd[1] : 파이프에 내용을 적습니다. 쉽게 설명을 하면 'O_WRONLY'라고 할 수 있습니다. 

반환 값은 성공 시 0을 리턴하고 실패 시 -1을 리턴합니다. 

 

이제 원리에 대해 살펴보도록 하겠습니다. 

우선 'pipe(int fd[2])'명령어를 통해 pipe를 생성하고 'fork()'를 통해 자식 프로세스가 생성이 되었다고 가정을 하겠습니다. 

 

위의 fork에 대한 블로그를 읽으셔서 아시겠지만 'fork()'명령어 이전에 발생된 프로세스상태를 그대로 복사하는 것입니다. 

그런데 pipe는 부모 프로세스에 생성이 되는 것이 아니라 독립적인 메모리 공간에 생성이 되어 이는 부모 프로세스에도 자식 프로세스에도 존재하지 않습니다. 

그렇기 때문에 자식 프로세스와 부모 프로세스는 pipe의 fd 외에는 pipe와 관련된 어떠한 메모리도 가지고 있지 않게 됩니다. 

이걸 그림으로 조금 나타내 보도록 하겠습니다. 

 

여기서 저는 자식 프로세스에서 부모 프로세스로 정보를 전달하고 싶습니다. 그면 필요 없는 fd는 닫아야 합니다. 

부모 프로세스는 fd[1]을 자식 프로세스는 fd[0]을 파이프와의 연결을 끊으면 됩니다. 

 

 

이를 코드로 한번 작성해 보도록 하겠습니다. 

 

아래의 내용을 이해하기 위해서는 몇 가지 개념이 더 필요합니다. dup2, wait, fork에 대해 아직은 모르시는 분들은 아래의 링크를 참고해 주세요.

dup2에 대해...

https://hig0617.tistory.com/138

wiat에 대해...

https://hig0617.tistory.com/135

fork에 대해...

https://hig0617.tistory.com/134

 

자식 프로세스에서 한 말을 pipe로 부모 프로세스에게 전달하도록 하겠습니다. 

 

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    int     pipefd[2];
    int     ret;
    char    buffer[100];
    int     status;
    pid_t   child_pid;

    pipe(pipefd);
    child_pid = fork();
    if (child_pid < 0)
        return (0);
    if (child_pid == 0)
    {
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO);
        printf("Hello, world! I am child proess.\n");
    }
    else
    {
        wait(&status);
        close(pipefd[1]);
        dup2(pipefd[0], STDIN_FILENO);
        ret = read(0, buffer, 100);
        if (ret < 0)
            return (0);
        buffer[ret] = '\0';
        printf("I am parent process, read from pipe : %s", buffer);
    }
    return (0);
}

 

출력 값입니다. 

I am parent process, read from pipe : Hello, world! I am child proess.

 

LIST

'Language > C언어' 카테고리의 다른 글

C057_execve함수 설명  (1) 2024.01.15
C056_C언어에 환경 변수 사용하기  (1) 2024.01.14
C054_open 함수 사용하기  (0) 2024.01.12
C053_dup2 함수 사용하기  (0) 2024.01.11
C052_dup 함수 사용하기  (0) 2024.01.10