[Linux] 공유 메모리 알아보기: shm_open, shm_unlink, mmap, munmap, ftruncate, usleep

Ma_Seokjae·2024년 4월 16일
0
post-thumbnail

이번 글에서는 운영체제 과제를 수행하며 다뤘던 공유 메모리 생성메시지 통신 기법에 대해 알아보려고 합니다

공유 메모리(Shared memory)?

공유 메모리(Shared memory)컴퓨터 환경에서 여러 프로그램이 동시에 접근할 수 있는 메모리이다. 과다한 복사를 피하거나 해당 프로그램 간 통신을 위해 고안되었다. 환경에 따라 프로그램은 하나의 프로세서에서나 여러 개의 프로세서에서 실행할 수 있다. (예를 들어 여러 개의 스레드 간에) 하나의 프로그램 안에서 통신을 위해 메모리를 사용하는 일은 일반적으로 공유 메모리로 부르지 않는다.

출처: https://ko.wikipedia.org/wiki/%EA%B3%B5%EC%9C%A0_%EB%A9%94%EB%AA%A8%EB%A6%AC

공유 메모리 사용? When..?

프로세스 간 통신: 서로 다른 프로세스들이 데이터를 공유하고 통신해야 하는 경우에 사용됩니다. 예를 들어, 한 프로세스가 생성한 데이터를 다른 프로세스가 사용해야 하는 경우에 공유 메모리를 활용할 수 있습니다.

병렬 컴퓨팅: 병렬 컴퓨팅 환경에서 여러 프로세스나 스레드가 동시에 작업을 수행하고 서로의 결과를 공유해야 할 때 사용됩니다. 이를 통해 병렬 처리 성능을 향상시킬 수 있습니다.

고성능 및 실시간 응용: 데이터를 빠르게 처리하고 실시간으로 반응해야 하는 응용 프로그램에서 사용됩니다. 공유 메모리는 데이터를 직접 메모리에 접근하여 처리하기 때문에 빠른 속도를 제공합니다.

자원 공유 및 최적화: 여러 프로세스가 동일한 데이터나 자원을 공유해야 하는 경우에 사용됩니다. 이를 통해 자원의 중복 사용을 최소화하고 메모리 사용량을 최적화할 수 있습니다.

[사용 시 주의할 점]

  • 동기화: 여러 프로세스가 동시에 공유 메모리에 접근하면 데이터 일관성을 유지하기 위해 동기화가 필요하게 됩니다. 그렇기 때문에 데이터를 읽고 쓰는 시점을 조절하여 경쟁 상태나 일관성 문제를 방지해야 합니다.

  • 보안: 공유 메모리를 사용하는 경우에는 보안 문제에 대해 신중해야 합니다. 민감한 데이터가 노출되지 않도록 적절한 보호 방법이 필요하며, 접근에 대한 권한을 잘 제어해서 의도치 않은 위험 접근을 방지해야 합니다.

  • 자원 누출: 공유 메모리를 사용할 때는 메모리 누출이 발생하지 않도록 주의해야 합니다. 메모리를 할당한 후에는 반드시 메모리를 해체해서 자원을 반환해야 안전합니다.

  • 데드락: 여러 프로세스가 공유 메모리를 사용하는 경우에는 데드락이 발생할 수 있습니다. 이를 방지하기 위해서 데드락을 탐지하고 해결하는 메커니즘이 필요합니다.

  • 성능 저하: 너무 많은 프로세스가 동시에 공유 메모리를 사용하면 성능이 저하될 수 있습니다. 이를 방지하기 위해서 적절한 메모리 및 자원 관리가 필요합니다.


공유 메모리 관리 함수

1. shm_open 함수

공유 메모리 객체를 생성하거나 열기 위해 사용됩니다

  • int shm_open(const char *name, int oflag, mode_t mode);
  • 파라미터 정보:
    • name: 공유 메모리 객체의 이름을 지정
    • oflag: 파일의 옵션을 지정, 주요 옵션으론 'O_CREAT', 'O_RDWR'
    • mode: 생성된 파일의 권한을 지정
  • 반환 값:
    • 성공 시: 파일 디스크립터
    • 실패 시: -1

예시:

int fd = shm_open("/my_shared_memory", O_CREAT | O_RDWR, 0666);
if (fd == -1) {
    perror("shm_open");
    exit(EXIT_FAILURE);
}

주의할 점!
name 파라미터에 공유 메모리 경로를 작성할 때에는 꼭 이름 앞에 '/'이 존재해야 함

공유 메모리 객체를 삭제할 때 사용됩니다

  • int shm_unlink(const char *name);
  • 파라미터 정보:
    • name: 삭제할 공유 메모리 객체의 이름을 지정
  • 반환 값:
    • 성공 시: 0
    • 실패 시: -1

예시:

if (shm_unlink("/my_shared_memory") == -1) {
    perror("shm_unlink");
    exit(EXIT_FAILURE);
}

3. mmap 함수

파일을 메모리에 매핑하거나 메모리를 할당할 때 사용됩니다

  • void mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset);
  • 파라미터 정보:
    • addr: 메모리 주소를 지정합니다. 일반적으로 'NULL'을 사용
    • length: 메모리 영역의 크기를 지정
    • prot: 메모리 영역의 보호 모드를 지정, 주요 모드로는 'PROT_READ', 'PROT_WRITE'
    • flags: 메모리 매핑 옵션을 지정
    • fd: 파일 디스크립터를 지정
    • offset: 파일 내의 오프셋을 지정
  • 반환 값:
    • 성공 시: 메모리 매핑된 영역의 시작 주소
    • 실패 시: 'MAP_FAILED' 메크로 반환

flag 정보:

  • MAP_SHARED:
    • 메모리 매핑을 공유 매핑으로 지정
    • 이 옵션을 사용하면 해당 메모리 영역에 대한 변경 사항이 다른 프로세스와 공유
  • MAP_PRIVATE:
    • 메모리 매핑을 개인 매핑으로 지정
    • 이 옵션을 사용하면 해당 메모리 영역에 대한 변경 사항이 다른 프로세스와 공유되지 않으며, 개인 매핑은 수정 가능하며 해당 영역에 대한 변경 사항은 메모리에만 반영
  • MAP_ANONYMOUS:
    • 파일 대신 익명 메모리 매핑을 생성
    • 이 옵션을 사용하면 파일 디스크립터(fd)와 오프셋(offset)을 지정하지 않아도 됩니다.
  • MAP_FIXED:
    • 사용자가 원하는 특정 주소(addr)에 매핑
    • 해당 주소가 이미 사용 중이거나 유효하지 않은 경우 매핑에 실패
  • MAP_FIXED_NOREPLACE:
    • MAP_FIXED와 유사하지만, 해당 주소에 이미 다른 메모리 매핑이 존재하는 경우 매핑에 실패
  • MAP_NORESERVE:
    • 메모리 매핑에 대한 페이지 예약을 하지 않음
    • 이 옵션을 사용하면 페이지 테이블에 대한 예약이 없기 때문에 메모리 할당에 실패할 수 있음
  • MAP_GROWSDOWN:
    • 스택 방향으로 메모리 매핑을 확장
    • 이 옵션을 사용하면 매핑된 메모리 영역의 끝에서부터 아래쪽으로 스택이 자동으로 확장
  • MAP_LOCKED:
    • 메모리 매핑을 락드 메모리로 지정
    • 락드 메모리는 페이지 전체를 항상 물리적 메모리에 로드하여 페이지 폴트를 방지
  • MAP_POPULATE:
    • 매핑된 메모리를 초기화하기 위해 가능한 경우 페이지를 물리적 메모리에 로드
    • 이 옵션을 사용하면 페이지 폴트를 초기화 단계에서 발생시킬 수 있음
  • MAP_HUGETLB:
    • 대용량 페이지를 사용하여 메모리를 매핑
    • 이 옵션을 사용하면 대용량 페이지를 사용하여 메모리를 매핑하여 성능을 향상시킴

예시:

void *shm_ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_ptr == MAP_FAILED) {
    perror("mmap");
    exit(EXIT_FAILURE);
}

4. munmap 함수

메모리 매핑을 해제할 때 사용됩니다

  • int munmap(void *addr, size_t length);
  • 파라미터 정보:
    • addr: 해제할 메모리 영역의 시작 주소를 지정
    • length: 해제할 메모리 영역의 크기를 지정
  • 반환 값:
    • 성공 시: 0
    • 실패 시: -1

예시:

if (munmap(shm_ptr, 4096) == -1) {
    perror("munmap");
    exit(EXIT_FAILURE);
}

5. ftruncate 함수

파일의 크기를 변경할 때 사용됩니다

  • int ftruncate(int fd, off_t length);
  • 파라미터 정보:
    • fd: 파일 디스크립터를 지정
    • length: 변경할 파일의 크키를 지정
  • 반환 값:
    • 성공 시: 0
    • 실패 시: -1

예시:

if (ftruncate(fd, 4096) == -1) {
    perror("ftruncate");
    exit(EXIT_FAILURE);
}

6. usleep 함수

일정 시간동안 프로세스를 대기시킬 때 사용됩니다

  • int usleep(useconds_t usec);
  • 파라미터 정보:
    • usec: 대기할 마이크로초 단위의 시간을 지정
  • 반환 값:
    • 성공 시: 0
    • 실패 시: -1

예시:

usleep(1000000); // 1초 동안 대기
profile
Why not change the code?

0개의 댓글

관련 채용 정보