Interview/OS

Multiprocess간 IPC 중 공유 메모리

김 정출 2024. 9. 28. 10:07

Multiprocess간 통신 방법

Multiprocess 간의 통신(IPC, Inter-Process Communication)은 서로 다른 프로세스가 데이터를 주고받거나 리소스를 공유하는 방법입니다. 운영체제에서 프로세스는 독립된 메모리 공간을 가지기 때문에 직접적으로 데이터를 공유할 수 없습니다. 따라서 IPC 기법을 사용하여 프로세스 간의 데이터를 전달하거나 동기화해야 합니다.

LinuxUnix에서 사용하는 다양한 IPC 방법들을 아래에 설명합니다.

3. 공유 메모리 (Shared Memory)

  • 공유 메모리는 여러 프로세스가 같은 메모리 공간을 공유하여 데이터를 주고받는 방법입니다. 가장 빠른 IPC 방법 중 하나로, 프로세스 간에 직접적인 메모리 접근을 가능하게 합니다.
  • 하지만, 동기화 문제가 발생할 수 있어, 이를 해결하기 위해 세마포어 같은 동기화 도구가 필요합니다.

공유 메모리 동작

  • shmget(): 공유 메모리 블록을 생성하거나 가져옵니다.
  • shmat(): 생성된 공유 메모리 블록을 프로세스의 주소 공간에 매핑합니다.
  • shmdt(): 매핑된 공유 메모리를 프로세스에서 분리합니다.
  • shmctl(): 공유 메모리의 제어 작업을 수행합니다 (삭제, 상태 조회 등).

이 방법은 데이터가 매우 빠르게 전달되지만, 동기화 제어가 복잡해질 수 있습니다.

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>

#define KEY 1234  // 공유 메모리를 식별할 키
#define SIZE 1024  // 공유 메모리 크기 (1KB)

int main() {
    int shmid;
    char *shmaddr;

    // 1. 공유 메모리 세그먼트 생성
    shmid = shmget(KEY, SIZE, IPC_CREAT | 0666);  // 0666은 읽기/쓰기 권한
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }

    // 2. 공유 메모리를 현재 프로세스에 연결
    shmaddr = (char *)shmat(shmid, NULL, 0);  // NULL을 주면 시스템이 자동으로 주소를 할당
    if (shmaddr == (char *)-1) {
        perror("shmat failed");
        return 1;
    }

    // 3. 공유 메모리에 데이터 쓰기
    strcpy(shmaddr, "Hello from shared memory!");

    printf("Data written to shared memory: %s\n", shmaddr);

    // 4. 공유 메모리 분리
    if (shmdt(shmaddr) == -1) {
        perror("shmdt failed");
        return 1;
    }

    return 0;
}

// 다른 프로그램
int main() {
    int shmid;
    char *shmaddr;

    // 1. 공유 메모리 세그먼트 가져오기
    shmid = shmget(KEY, SIZE, 0666);  // 이미 생성된 공유 메모리 세그먼트 가져오기
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }

    // 2. 공유 메모리를 현재 프로세스에 연결
    shmaddr = (char *)shmat(shmid, NULL, 0);  // NULL을 주면 시스템이 자동으로 주소를 할당
    if (shmaddr == (char *)-1) {
        perror("shmat failed");
        return 1;
    }

    // 3. 공유 메모리에서 데이터 읽기
    printf("Data read from shared memory: %s\n", shmaddr);

    // 4. 공유 메모리 분리
    if (shmdt(shmaddr) == -1) {
        perror("shmdt failed");
        return 1;
    }

    // 5. 공유 메모리 삭제
    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
        perror("shmctl failed");
        return 1;
    }

    printf("Shared memory deleted successfully.\n");

    return 0;
}

공유 메모리의 장점

  1. 빠른 데이터 전송:
    • 공유 메모리는 데이터를 메모리에서 바로 읽고 쓰기 때문에, 다른 IPC(Inter-Process Communication) 방법들보다 매우 빠른 속도를 제공합니다. 데이터를 복사하지 않고, 동일한 메모리 영역을 여러 프로세스가 참조하므로, 처리 속도가 월등히 빠릅니다.
  2. 대용량 데이터 처리:
    • 공유 메모리는 대용량 데이터 전송에 적합합니다. 파일, 소켓, 메시지 큐 등의 다른 IPC 방식들은 제한된 크기의 버퍼나 메모리만 사용할 수 있는 반면, 공유 메모리는 메모리 크기만큼 데이터를 공유할 수 있습니다.
  3. 낮은 자원 소모:
    • 데이터를 복사하는 과정이 없기 때문에 CPU 자원 소모가 적고 효율적입니다. 다른 IPC 방식은 데이터를 주고받을 때 복사 과정이 필요하지만, 공유 메모리는 데이터를 공유하는 프로세스들이 동일한 메모리 주소 공간을 참조합니다.
  4. 동기화된 데이터 접근:
    • 모든 프로세스가 동일한 데이터에 접근할 수 있기 때문에, 상태를 공유하고 실시간으로 변화하는 데이터를 동기화하는 데 매우 유리합니다. 이를 통해 프로세스 간 협업이 용이해집니다.
  5. 간단한 구조:
    • 한 번 설정되면, 각 프로세스가 공유 메모리를 직접 참조하여 데이터를 읽거나 쓸 수 있습니다. 이는 파일을 열고 읽거나 쓰는 작업에 비해 매우 단순하고 직관적입니다.

공유 메모리의 단점

  • 공유 메모리는 빠르고 효율적이지만, 동기화 문제(예: 여러 프로세스가 동시에 쓰기 작업을 할 때 충돌)나 보안 문제(데이터에 대한 접근 제어가 어려움)가 발생할 수 있습니다. 이를 해결하기 위해서는 세마포어뮤텍스 같은 동기화 메커니즘을 함께 사용해야 합니다.