What is IPC?

  Inter Process Communication는 하나의 프로세스가 다른 프로세스로 대화를 거는 방법입니다. 이미 가상 메모리에서 본 적이 있습니다. mmap을 이용하면 가상 메모리를 부모와 자식이 공유하여 communication이 가능해집니다. 이 메모리의 race condition을 막기 위해서 그 메모리를 pthread_mutexatter_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED); mutex(or a process wide mutex)를 감쌀 수 있습니다.
  가장 일반적인 IPC 방법으로는 파이프가 있습니다. 터미널에 다음과 같은 입력을 해 봅시다.

$ ls -1 | cut -d'.' -f1 | uniq | sort | tee dir_contents

위 코드는 어떤 일을 할까요? ls는 현재 디렉토리 정보를 나타냅니다(-l은 결과를 줄로 보여달라는 의미입니다). 다음 cut 명령어는 .부분을 잘라냅니다. 다음 unique는 모든 라인이 중복되지 않고 하나만 존재하도록 하고, sort는 정렬을 시켜주고 tee는 파일로 아웃풋을 보내줍니다.


위 과정에서 중요한 점은 bash가 5개의 분리된 프로세스를 생성해 아래와 같이 프로세스들의 standard out과 in을 연결했다는 것입니다.


(0) ls (1)------>(0) cut (1)------->(0) uniq (1)------>(0) sort (1)------>(0) tee (1)


파이프의 숫자는 각각의 프로세스의 file descriptor입니다. 화살표는 redirect 또는 파이프의 output이 가는 곳을 의미합니다.


What is pipe?

POSIX의 파이프는 실제 파이프와 거의 같습니다. 한 쪽 끝에서 바이트를 채우면 다른 쪽에서도 같은 순서로 나타날 것입니다. 실제 파이프와는 다르게, 항상 한쪽 방향으로만 흐름이 생겨 한 파일 디스크립터는 오직 읽는데만 사용되고 다른 하나는 쓰기에 사용됩니다. pipe의 system call을 pipe를 만드는 데 사용됩니다.


int filedes[2];
pipe (filedes);
printf("read from %d, write to %d\n", filedes[0], filedes[1]);


이러한 file descriptor는 read와 사용되어질 수 있습니다.


// To read...
char buffer[80];
int bytesread = read(filedes[0], buffer, sizeof(buffer));


또는, 아래와 같이 child process에서 write를 통해 부모에게 메세지를 보내는데 사용되어 질 수도 있습니다.


if (child == 0) {
   write(filedes[1], "done", 4);
}



Can I use pipe inside a single process?

물론 하나의 프로세스 안에서 사용하는 것도 가능하지만, 굳이 그렇게 사용할 필요가 있을까요?

다음은 스스로에게 message를 보내는 프로그램입니다.

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

int main() {
    int fh[2];
    pipe(fh);
    FILE *reader = fdopen(fh[0], "r");
    FILE *writer = fdopen(fh[1], "w");
    // Hurrah now I can use printf rather than using low-level read() write()
    printf("Writing...\n");
    fprintf(writer,"%d %d %d\n", 10, 20, 30);
    fflush(writer);
    
    printf("Reading...\n");
    int results[3];
    int ok = fscanf(reader,"%d %d %d", results, results + 1, results + 2);
    printf("%d values parsed: %d %d %d\n", ok, results[0], results[1], results[2]);
    
    return 0;
}


이러한 방식으로 파이프를 사용하는 방법의 문제는 파이프의 버퍼가 제한된 경우에 파이프에 쓰는 것이 블록을 일크킬 수 있다는 것입니다. 만약 파이프가 쓰기로 가득 차면 프로세스는 블록될 것입니다. 버퍼의 최대 크기는 시스템에 의존적이지만, 일반적으로 4KB에서 128KB까지입니다.


int main() {
    int fh[2];
    pipe(fh);
    int b = 0;
    #define MESG "..............................."
    while(1) {
        printf("%d\n",b);
        write(fh[1], MESG, sizeof(MESG))
        b+=sizeof(MESG);
    }
    return 0;
}


Posted by 몰랑&봉봉
,