프로세스 간 통신-파이프

파이프는 둘 이상의 관련되거나 상호 관련된 프로세스 간의 통신 매체입니다. 하나의 프로세스 내에 있거나 하위 프로세스와 상위 프로세스 간의 통신 일 수 있습니다. 통신은 또한 부모, 자식 및 손자 간의 통신 등과 같이 다단계 일 수 있습니다. 통신은 파이프에 쓰는 한 프로세스와 파이프에서 다른 읽기를 통해 이루어집니다. 파이프 시스템 호출을 수행하려면 두 개의 파일을 작성하십시오. 하나는 파일에 쓰고 다른 하나는 파일에서 읽을 수 있습니다.

파이프 메커니즘은 파이프로 물을 일부 컨테이너 (예 : 버킷)에 채우고 누군가가이를 가져 오는 경우 (예 : 머그잔으로)와 같은 실시간 시나리오로 볼 수 있습니다. 채우는 과정은 파이프에 쓰는 것에 지나지 않으며 읽기 과정은 파이프에서 검색하는 것입니다. 이것은 하나의 출력 (물)이 다른 하나 (버킷)에 대한 입력임을 의미합니다.

#include<unistd.h>

int pipe(int pipedes[2]);

이 시스템 호출은 단방향 통신을위한 파이프를 생성합니다. 즉, 두 개의 디스크립터를 생성합니다. 첫 번째는 파이프에서 읽기 위해 연결되고 다른 하나는 파이프에 쓰기 위해 연결됩니다.

설명자 pipedes [0]은 읽기 용이고 pipedes [1]은 쓰기 용입니다. pipedes [1]에 기록 된 내용은 pipedes [0]에서 읽을 수 있습니다.

이 호출은 성공하면 0을 반환하고 실패하면 -1을 반환합니다. 실패의 원인을 알려면 errno 변수 또는 perror () 함수로 확인하십시오.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

파일에 대한 기본 작업은 읽기 및 쓰기이지만 작업을 수행하기 전에 파일을 열고 필요한 작업을 완료 한 후 파일을 닫는 것이 필수적입니다. 일반적으로 기본적으로 모든 프로세스에 대해 3 개의 설명자가 열리 며, 이는 각각 파일 설명자가 0, 1 및 2 인 입력 (표준 입력 – stdin), 출력 (표준 출력 – stdout) 및 오류 (표준 오류 – stderr)에 사용됩니다.

이 시스템 호출은 읽기 / 쓰기 / 검색 (lseek)의 추가 파일 작업에 사용되는 파일 설명자를 반환합니다. 일반적으로 파일 설명자는 3부터 시작하여 파일이 열리면 숫자가 하나씩 증가합니다.

개방형 시스템 호출에 전달 된 인수는 경로 이름 (상대 또는 절대 경로), 파일 열기 목적을 언급하는 플래그 (예 : 읽기 용 열기, O_RDONLY, 쓰기 용, O_WRONLY, 읽기 및 쓰기 용, O_RDWR, 기존 파일에 추가하기)입니다. O_APPEND, O_CREAT와 함께 존재하지 않는 경우 파일 생성) 및 사용자 또는 소유자 / 그룹 / 기타에게 읽기 / 쓰기 / 실행 권한을 제공하는 필수 모드. 모드는 기호로 언급 할 수 있습니다.

읽기 – 4, 쓰기 – 2 및 실행 – 1.

예 : 8 진수 값 (0으로 시작), 0764는 소유자에게 읽기, 쓰기 및 실행 권한이 있음, 그룹에 읽기 및 쓰기 권한이 있음, 다른 그룹에 읽기 권한 있음을 의미합니다. 이것은 S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH, 이는 0700 | 0040 | 0020 | 0004 → 0764를 의미하거나 작동합니다.

이 시스템 호출이 성공하면 새 파일 설명자 ID를 반환하고 오류가 발생하면 -1을 반환합니다. 오류의 원인은 errno 변수 또는 perror () 함수로 식별 할 수 있습니다.

#include<unistd.h>

int close(int fd)

위의 시스템 호출은 이미 열린 파일 설명자를 닫습니다. 이는 파일이 더 이상 사용되지 않으며 연관된 리소스를 다른 프로세스에서 재사용 할 수 있음을 의미합니다. 이 시스템 호출은 성공시 0을, 오류시 -1을 반환합니다. 오류의 원인은 errno 변수 또는 perror () 함수로 식별 할 수 있습니다.

#include<unistd.h>

ssize_t read(int fd, void *buf, size_t count)

위의 시스템 호출은 파일 설명자 fd의 인수, 할당 된 메모리 (정적 또는 동적)가있는 적절한 버퍼 및 버퍼 크기를 사용하여 지정된 파일에서 읽는 것입니다.

파일 디스크립터 ID는 open () 또는 pipe () 시스템 호출을 호출 한 후 반환되는 각 파일을 식별하는 것입니다. 파일에서 읽기 전에 파일을 열어야합니다. pipe () 시스템 호출시 자동으로 열립니다.

이 호출은 성공시 읽은 바이트 수 (또는 파일 끝을 발견하는 경우 0)를 반환하고 실패시 -1을 반환합니다. 반환 바이트는 데이터를 사용할 수 없거나 파일이 닫힌 경우 요청 된 바이트 수보다 작을 수 있습니다. 장애 발생시 적절한 오류 번호가 설정됩니다.

실패의 원인을 알려면 errno 변수 또는 perror () 함수로 확인하십시오.

#include<unistd.h>

ssize_t write(int fd, void *buf, size_t count)

위의 시스템 호출은 파일 설명자 fd의 인수, 할당 된 메모리 (정적 또는 동적)가있는 적절한 버퍼 및 버퍼 크기를 사용하여 지정된 파일에 쓰는 것입니다.

파일 디스크립터 ID는 open () 또는 pipe () 시스템 호출을 호출 한 후 반환되는 각 파일을 식별하는 것입니다.

파일에 쓰기 전에 파일을 열어야합니다. pipe () 시스템 호출시 자동으로 열립니다.

이 호출은 성공시 기록 된 바이트 수 (또는 아무것도 기록되지 않은 경우 0)를 반환하고 실패시 -1을 반환합니다. 장애 발생시 적절한 오류 번호가 설정됩니다.

실패의 원인을 알려면 errno 변수 또는 perror () 함수로 확인하십시오.

예제 프로그램

다음은 몇 가지 예제 프로그램입니다.

Example program 1 − 파이프를 사용하여 두 개의 메시지를 쓰고 읽는 프로그램.

연산

Step 1 − 파이프를 생성합니다.

Step 2 − 파이프에 메시지를 보냅니다.

Step 3 − 파이프에서 메시지를 검색하여 표준 출력에 씁니다.

Step 4 − 파이프에 다른 메시지를 보냅니다.

Step 5 − 파이프에서 메시지를 검색하여 표준 출력에 씁니다.

Note − 모든 메시지를 보낸 후 메시지 검색을 수행 할 수도 있습니다.

Source Code: simplepipe.c

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

int main() {
   int pipefds[2];
   int returnstatus;
   char writemessages[2][20]={"Hi", "Hello"};
   char readmessage[20];
   returnstatus = pipe(pipefds);
   
   if (returnstatus == -1) {
      printf("Unable to create pipe\n");
      return 1;
   }
   
   printf("Writing to pipe - Message 1 is %s\n", writemessages[0]);
   write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
   read(pipefds[0], readmessage, sizeof(readmessage));
   printf("Reading from pipe – Message 1 is %s\n", readmessage);
   printf("Writing to pipe - Message 2 is %s\n", writemessages[0]);
   write(pipefds[1], writemessages[1], sizeof(writemessages[0]));
   read(pipefds[0], readmessage, sizeof(readmessage));
   printf("Reading from pipe – Message 2 is %s\n", readmessage);
   return 0;
}

Note− 이상적으로는 모든 시스템 호출에 대해 반환 상태를 확인해야합니다. 프로세스를 단순화하기 위해 모든 호출에 대해 확인이 수행되지는 않습니다.

실행 단계

편집

gcc -o simplepipe simplepipe.c

실행 / 출력

Writing to pipe - Message 1 is Hi
Reading from pipe – Message 1 is Hi
Writing to pipe - Message 2 is Hi
Reading from pipe – Message 2 is Hell

Example program 2 − 부모와 자식 프로세스를 사용하여 파이프를 통해 두 개의 메시지를 쓰고 읽는 프로그램.

연산

Step 1 − 파이프를 생성합니다.

Step 2 − 하위 프로세스를 생성합니다.

Step 3 − 상위 프로세스가 파이프에 기록합니다.

Step 4 − 하위 프로세스는 파이프에서 메시지를 검색하여 표준 출력에 기록합니다.

Step 5 − 3 단계와 4 단계를 다시 한 번 반복합니다.

Source Code: pipewithprocesses.c

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

int main() {
   int pipefds[2];
   int returnstatus;
   int pid;
   char writemessages[2][20]={"Hi", "Hello"};
   char readmessage[20];
   returnstatus = pipe(pipefds);
   if (returnstatus == -1) {
      printf("Unable to create pipe\n");
      return 1;
   }
   pid = fork();
   
   // Child process
   if (pid == 0) {
      read(pipefds[0], readmessage, sizeof(readmessage));
      printf("Child Process - Reading from pipe – Message 1 is %s\n", readmessage);
      read(pipefds[0], readmessage, sizeof(readmessage));
      printf("Child Process - Reading from pipe – Message 2 is %s\n", readmessage);
   } else { //Parent process
      printf("Parent Process - Writing to pipe - Message 1 is %s\n", writemessages[0]);
      write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
      printf("Parent Process - Writing to pipe - Message 2 is %s\n", writemessages[1]);
      write(pipefds[1], writemessages[1], sizeof(writemessages[1]));
   }
   return 0;
}

실행 단계

Compilation

gcc pipewithprocesses.c –o pipewithprocesses

Execution

Parent Process - Writing to pipe - Message 1 is Hi
Parent Process - Writing to pipe - Message 2 is Hello
Child Process - Reading from pipe – Message 1 is Hi
Child Process - Reading from pipe – Message 2 is Hello

파이프를 사용한 양방향 통신

파이프 통신은 단방향 통신으로 간주됩니다. 즉, 부모 프로세스가 쓰고 자식 프로세스가 읽거나 그 반대의 경우도 마찬가지입니다. 그러나 부모와 자식이 동시에 파이프에서 쓰고 읽어야하는 경우 솔루션은 파이프를 사용한 양방향 통신입니다. 양방향 통신을 설정하려면 두 개의 파이프가 필요합니다.

다음은 양방향 통신을 달성하는 단계입니다.

Step 1− 두 개의 파이프를 생성합니다. 첫 번째는 pipe1과 같이 부모가 쓰고 자식이 읽는 것입니다. 두 번째는 pipe2와 같이 자식이 쓰고 부모가 읽을 수 있도록하는 것입니다.

Step 2 − 하위 프로세스를 생성합니다.

Step 3 − 각 통신에 한쪽 끝만 필요하므로 원하지 않는 끝을 닫습니다.

Step 4 − 부모 프로세스에서 원하지 않는 끝을 닫고 pipe1의 끝을 읽고 pipe2의 끝을 씁니다.

Step 5 − 자식 프로세스에서 원하지 않는 끝을 닫고 pipe1의 끝을 쓰고 pipe2의 끝을 읽습니다.

Step 6 − 필요에 따라 통신을 수행하십시오.

샘플 프로그램

Sample program 1 − 파이프를 사용한 양방향 통신 달성.

연산

Step 1 − 부모 프로세스가 쓰고 자식 프로세스가 읽을 pipe1을 생성하십시오.

Step 2 − 쓸 하위 프로세스와 읽을 상위 프로세스에 대해 pipe2를 생성합니다.

Step 3 − 상위 및 하위 쪽에서 파이프의 원하지 않는 끝을 닫습니다.

Step 4 − 메시지를 쓰는 부모 프로세스와 화면에 읽고 표시 할 자식 프로세스.

Step 5 − 메시지를 작성하는 하위 프로세스와 화면에 읽고 표시 할 상위 프로세스.

Source Code: twowayspipe.c

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

int main() {
   int pipefds1[2], pipefds2[2];
   int returnstatus1, returnstatus2;
   int pid;
   char pipe1writemessage[20] = "Hi";
   char pipe2writemessage[20] = "Hello";
   char readmessage[20];
   returnstatus1 = pipe(pipefds1);
   
   if (returnstatus1 == -1) {
      printf("Unable to create pipe 1 \n");
      return 1;
   }
   returnstatus2 = pipe(pipefds2);
   
   if (returnstatus2 == -1) {
      printf("Unable to create pipe 2 \n");
      return 1;
   }
   pid = fork();
   
   if (pid != 0) // Parent process {
      close(pipefds1[0]); // Close the unwanted pipe1 read side
      close(pipefds2[1]); // Close the unwanted pipe2 write side
      printf("In Parent: Writing to pipe 1 – Message is %s\n", pipe1writemessage);
      write(pipefds1[1], pipe1writemessage, sizeof(pipe1writemessage));
      read(pipefds2[0], readmessage, sizeof(readmessage));
      printf("In Parent: Reading from pipe 2 – Message is %s\n", readmessage);
   } else { //child process
      close(pipefds1[1]); // Close the unwanted pipe1 write side
      close(pipefds2[0]); // Close the unwanted pipe2 read side
      read(pipefds1[0], readmessage, sizeof(readmessage));
      printf("In Child: Reading from pipe 1 – Message is %s\n", readmessage);
      printf("In Child: Writing to pipe 2 – Message is %s\n", pipe2writemessage);
      write(pipefds2[1], pipe2writemessage, sizeof(pipe2writemessage));
   }
   return 0;
}

실행 단계

편집

gcc twowayspipe.c –o twowayspipe

실행

In Parent: Writing to pipe 1 – Message is Hi
In Child: Reading from pipe 1 – Message is Hi
In Child: Writing to pipe 2 – Message is Hello
In Parent: Reading from pipe 2 – Message is Hello