C의 다중 파이프

Waqar Aslam 2023년10월12일
  1. C의 파이프 개요
  2. C에서 다중 파이프 구현
C의 다중 파이프

이 기사에서는 C에서 여러 파이프를 구현하는 방법을 보여줍니다.

C의 파이프 개요

파이프는 한 프로세스에서 반환된 표준 출력이 다른 프로세스의 표준 입력이 되는 두 개의 서로 다른 프로세스 간의 링크를 추상적으로 표현한 것입니다. 파이프는 연결된 프로세스가 서로 통신(프로세스 간 통신)할 수 있도록 하는 UNIX 운영 체제의 중요한 구성 요소입니다.

파이프는 한 방향으로만 통신할 수 있습니다. 따라서 한 프로세스가 파이프에 쓰는 동안 다른 프로세스가 파이프에서 읽는 데 사용할 수 있습니다. 파이프는 가상 파일과 동일한 방식으로 처리되는 주 메모리 영역이며 이 작업으로 파이프가 열립니다.

C에서 다중 파이프 구현

1개의 상위 프로세스와 2개의 하위 프로세스가 있는 예를 살펴보겠습니다. 우리는 파이프를 통해 부모 프로세스에서 자식 프로세스로 완전함을 보장하는 값을 보낸 다음 그 값을 약간의 증가분을 추가하여 부모 프로세스로 다시 보냅니다.

시작하려면 애플리케이션에 포함된 클래스와 함수에 액세스하기 위해 라이브러리를 가져와야 합니다. 또한 main() 함수를 개발해야 합니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char* argv[]) {}

main 기능 내에서 세 개의 파이프에 대한 파일 설명자를 생성하여 다른 프로세스에서 읽고 쓸 수 있습니다. 그런 다음 i 유형의 변수를 정수로 정의하여 세 개의 파이프를 생성하는 for 루프를 설정하고 모든 파이프의 값이 0보다 작은지 확인하여 오류.

int fd[3][2];
int i;
for (i = 0; i < 3; i++) {
  if (pipe(fd[i]) < 0) {
    return 1;
  }
}

파이프 열기를 마친 후 다음 단계는 각 프로세스를 분기하기 시작하는 것입니다. 따라서 processIdOne이라는 변수를 설정한 다음 fork() 함수를 할당해야 합니다.

또한 processIdOne 값이 0 이상인지 확인하는 검사를 적용하십시오.

int processIdOne = fork();
if (processIdOne < 0) {
  return 2;
}

이제 processIdOne의 값이 0인지 확인합니다. 그렇다면 이것은 우리가 첫 번째 자식 프로세스에 있음을 나타냅니다. close() 함수는 이 프로세스에 속하는 파일 디스크립터를 제외한 모든 파일 디스크립터를 종료하기 위해 첫 번째 자식 프로세스 내부에서 사용해야 합니다.

x라는 이름으로 정수 변수를 생성하고 데이터 유형을 int로 지정합니다. 이제 read() 메서드를 사용하여 파일 디스크립터 &x와 값을 읽을 크기를 제공하고 값이 0보다 작은지 확인한 후 오류 메시지를 표시합니다. 이다.

다음으로 fileDescriptor[1][1] 값이 0보다 작은지 확인하고 그럴 경우 오류를 표시합니다. 우리는 write() 메서드를 활용하고 매개 변수를 전달하고 fileDescriptor[1][1]를 사용하여 작성합니다.

첫 번째 자식 프로세스의 파일 설명자는 마지막 단계에서 닫아야 합니다.

if (processIdOne == 0) {
  // Child process 1
  close(fileDescriptor[0][1]);
  close(fileDescriptor[1][0]);
  close(fileDescriptor[2][0]);
  close(fileDescriptor[2][1]);
  int x;
  if (read(fileDescriptor[0][0], &x, sizeof(int)) < 0) {
    return 3;
  }
  x += 10;
  if (write(fileDescriptor[1][1], &x, sizeof(int)) < 0) {
    return 4;
  }
  close(fileDescriptor[0][0]);
  close(fileDescriptor[1][1]);
  return 0;
}

다음 단계는 processIdTwo라는 변수를 설정한 다음 fork() 함수를 할당하는 것입니다. 또한 processIdTwo 값이 0 이하가 아닌지 확인하기 위해 검사를 수행해야 합니다.

int processIdTwo = fork();
if (processIdTwo < 0) {
  return 5;
}

이제 processIdTwo의 값이 0인지 확인합니다. 그렇다면 두 번째 하위 프로세스에 있음을 나타냅니다. 두 번째 하위 프로세스 내에서 이 특정 프로세스를 제외하고 close() 메서드를 사용하여 모든 파일 디스크립터가 닫히도록 해야 합니다.

x.라는 데이터 유형이 int인 변수를 선언합니다. 이제 read() 메서드를 사용하고 파일 설명자 &x와 값을 읽을 크기를 제공하고 값이 0보다 작은 경우 오류가 표시되도록 합니다.

다음으로 x 값에 10 값을 추가하여 값을 늘리고 fileDescriptor[2][1]를 사용하여 쓰기 위해 매개 변수와 함께 write() 함수를 사용합니다. 그런 다음 값이 0보다 작은지 확인하고 0이면 오류 메시지를 표시합니다.

마지막으로 두 번째 자식 프로세스의 파일 설명자를 닫습니다.

if (processIdTwo == 0) {
  close(fileDescriptor[0][0]);
  close(fileDescriptor[0][1]);
  close(fileDescriptor[1][1]);
  close(fileDescriptor[2][0]);
  int x;
  if (read(fileDescriptor[1][0], &x, sizeof(int)) < 0) {
    return 6;
  }
  x += 10;
  if (write(fileDescriptor[2][1], &x, sizeof(int)) < 0) {
    return 7;
  }
  close(fileDescriptor[1][0]);
  close(fileDescriptor[2][1]);
  return 0;
}

이전에 했던 것처럼 이제 이 프로세스에 해당하는 파일 디스크립터를 제외하고 상위 프로세스의 다른 모든 파일 디스크립터를 종료합니다.

변수 x를 정수 유형으로 선언하십시오. 이제 read() 함수를 사용하고 파일 설명자 &x와 값을 읽을 크기를 제공하고 값이 0보다 작은지 확인하여 오류를 표시해야 하는지 여부를 결정합니다.

다음으로 10 값을 추가하여 x 값을 증가시킵니다. write() 함수와 매개변수를 사용하여 fileDescriptor[2][0]를 사용하여 작성하고 값이 0보다 작은지 확인하여 오류 메시지를 표시할지 여부를 결정합니다.

열려 있는 파일 설명자를 닫아 중지합니다.

processIdOneprocessIdTwo 모두에 대해 waitpid() 메서드를 사용해야 합니다. 이 기능은 다음 작업으로 이동하기 전에 모든 프로세스가 완료될 때까지 기다립니다.

close(fileDescriptor[0][0]);
close(fileDescriptor[1][0]);
close(fileDescriptor[1][1]);
close(fileDescriptor[2][1]);
int x = 0;
if (write(fileDescriptor[0][1], &x, sizeof(int)) < 0) {
  return 8;
}
if (read(fileDescriptor[2][0], &x, sizeof(int)) < 0) {
  return 9;
}
printf("The value received from the child processes is: %d\n", x);
close(fileDescriptor[0][1]);
close(fileDescriptor[2][0]);

waitpid(processIdOne, NULL, 0);
waitpid(processIdTwo, NULL, 0);

C에서 다중 파이프를 구현하기 위한 완전한 소스 코드:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
  int fileDescriptor[3][2];
  int i;
  for (i = 0; i < 3; i++) {
    if (pipe(fileDescriptor[i]) < 0) {
      return 1;
    }
  }

  int processIdOne = fork();
  if (processIdOne < 0) {
    return 2;
  }

  if (processIdOne == 0) {
    // Child process 1
    close(fileDescriptor[0][1]);
    close(fileDescriptor[1][0]);
    close(fileDescriptor[2][0]);
    close(fileDescriptor[2][1]);
    int x;
    if (read(fileDescriptor[0][0], &x, sizeof(int)) < 0) {
      return 3;
    }
    x += 10;
    if (write(fileDescriptor[1][1], &x, sizeof(int)) < 0) {
      return 4;
    }
    close(fileDescriptor[0][0]);
    close(fileDescriptor[1][1]);
    return 0;
  }

  int processIdTwo = fork();
  if (processIdTwo < 0) {
    return 5;
  }

  if (processIdTwo == 0) {
    // Child process 2
    close(fileDescriptor[0][0]);
    close(fileDescriptor[0][1]);
    close(fileDescriptor[1][1]);
    close(fileDescriptor[2][0]);
    int x;
    if (read(fileDescriptor[1][0], &x, sizeof(int)) < 0) {
      return 6;
    }
    x += 10;
    if (write(fileDescriptor[2][1], &x, sizeof(int)) < 0) {
      return 7;
    }
    close(fileDescriptor[1][0]);
    close(fileDescriptor[2][1]);
    return 0;
  }

  // Parent process
  close(fileDescriptor[0][0]);
  close(fileDescriptor[1][0]);
  close(fileDescriptor[1][1]);
  close(fileDescriptor[2][1]);
  int x = 0;
  if (write(fileDescriptor[0][1], &x, sizeof(int)) < 0) {
    return 8;
  }
  if (read(fileDescriptor[2][0], &x, sizeof(int)) < 0) {
    return 9;
  }
  printf("The value received from the child processes is: %d\n", x);
  close(fileDescriptor[0][1]);
  close(fileDescriptor[2][0]);

  waitpid(processIdOne, NULL, 0);
  waitpid(processIdTwo, NULL, 0);

  return 0;
}

출력:

The value received from the child processes is: 20
작가: Waqar Aslam
Waqar Aslam avatar Waqar Aslam avatar

I am Waqar having 5+ years of software engineering experience. I have been in the industry as a javascript web and mobile developer for 3 years working with multiple frameworks such as nodejs, react js, react native, Ionic, and angular js. After which I Switched to flutter mobile development. I have 2 years of experience building android and ios apps with flutter. For the backend, I have experience with rest APIs, Aws, and firebase. I have also written articles related to problem-solving and best practices in C, C++, Javascript, C#, and power shell.

LinkedIn

관련 문장 - C Pipe