mmap 함수를 사용하여 C에서 메모리에 쓰기

Mehvish Ashiq 2023년10월12일
  1. C의 mmap() 함수
  2. mmap()을 사용하여 C에서 메모리에 쓰기
mmap 함수를 사용하여 C에서 메모리에 쓰기

이 기사에서는 mmap() 함수, 얼마나 많은 매개변수를 사용하는지, mmap()을 사용하여 C 프로그래밍에서 메모리에 쓰는 방법을 배웁니다.

C의 mmap() 함수

이 기능을 사용하여 프로세스 주소 공간과 장치 또는 파일을 매핑합니다. mmap() 함수는 쓰기 가능한 익명 및 메모리 n 바이트의 개인 매핑을 요청합니다.

익명 매핑 및 개인 매핑은 파일에 의해 지원되지 않으며 다른 프로세스와 공유되지 않음을 의미합니다. mmap()을 사용하려면 헤더 파일을 포함해야 합니다.

#include <sys/mman.h>

6개의 인수가 필요합니다.

void *mmap(void *address, size_t length, int protect, int flags, int filedes,
           off_t offset)

이 함수를 사용하기 전에 인수에 대해 논의해 봅시다.

  1. 주소 - 매핑에 사용되는 기본 시작 주소를 제공합니다. 다른 매핑이 없으면 커널은 가까운 페이지 경계를 선택하여 매핑을 생성합니다.

    그렇지 않으면 커널이 새 주소를 선택합니다. 이 매개변수의 값이 NULL인 경우 커널은 적절하다고 판단되는 위치에 매핑을 배치합니다.

  2. 길이 - 바이트 수가 매핑됩니다.

  3. 보호 - 허용되는 액세스 유형을 제어합니다. 예를 들어, 읽기 액세스를 위한 PROT_READ, 쓰기 액세스를 위한 PROT_WRITE, 실행을 위한 PROT_EXEC입니다.

  4. 플래그 - 맵의 특성을 제어하는 데 사용됩니다. 일반적이고 유용한 플래그 중 일부는 다음과 같습니다.

    • MAP_SHARED - 다른 프로세스와 매핑을 공유합니다.
    • MAP_FIXED - 시스템은 address 매개변수를 통해 제공된 동일한 매핑 주소를 사용하도록 강제됩니다.
    • MAP_ANONYMOUS / MAP_ANON - 익명 매핑을 생성합니다.
    • MAP_PRIVATE - 이 플래그를 사용하는 동안 매핑은 비공개이며 다른 사람에게 표시되지 않습니다.
  5. filedes - 파일 설명자는 매핑되어야 합니다.

  6. 오프셋 - 파일 매핑이 이 오프셋에서 시작됩니다.

mmap()이 성공적으로 작동하면 0을 얻습니다. 그렇지 않으면 MAP_FAILED가 반환됩니다.

mmap()을 사용하여 C에서 메모리에 쓰기

다양한 예제를 통해 mmap()을 이해해 봅시다.

예제 코드(메모리 할당):

#include <stdio.h>
#include <sys/mman.h>

int main() {
  int N = 5;
  int *ptr = mmap(NULL, N * sizeof(int), PROT_READ | PROT_WRITE,
                  MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);

  if (ptr == MAP_FAILED) {
    printf("Mapping Failed\n");
    return 1;
  }

  for (int i = 0; i < N; i++) ptr[i] = i * 10;

  for (int i = 0; i < N; i++) printf("[%d] ", ptr[i]);

  printf("\n");
  int err = munmap(ptr, 10 * sizeof(int));
  if (err != 0) {
    printf("Unmapping Failed\n");
    return 1;
  }

  return 0;
}

출력:

[0] [10] [20] [30] [40]

mmap() 함수를 사용하여 PROT_READ | PROT_WRITE 매핑된 영역에 대한 쓰기 및 읽기 보호.

매핑 영역을 다른 프로세스와 공유하고 싶지 않기 때문에 MAP_PRIVATE 플래그를 사용하고 파일을 매핑하지 않았기 때문에 MAP_ANONYMOUS 플래그를 사용합니다.

같은 이유로 파일 디스크립터와 오프셋이 0으로 설정됩니다.

예제 코드(프로세스 간 통신용):

#include <stdio.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
  int Number = 5;
  int *ptr = mmap(NULL, Number * sizeof(int), PROT_READ | PROT_WRITE,
                  MAP_SHARED | MAP_ANONYMOUS, 0, 0);

  if (ptr == MAP_FAILED) {
    printf("Mapping Failed\n");
    return 1;
  }

  for (int i = 0; i < Number; i++) {
    ptr[i] = i + 7;
  }

  printf("Initial array's values:");
  for (int i = 0; i < Number; i++) {
    printf(" %d", ptr[i]);
  }
  printf("\n");
  pid_t child_pid = fork();

  if (child_pid == 0) {
    // child
    for (int i = 0; i < Number; i++) {
      ptr[i] = ptr[i] * 5;
    }
  } else {
    // parent
    waitpid(child_pid, NULL, 0);
    printf("\nParent:\n");
    printf("Updated array's values:");
    for (int i = 0; i < Number; i++) {
      printf(" %d", ptr[i]);
    }
    printf("\n");
  }

  int err = munmap(ptr, Number * sizeof(int));

  if (err != 0) {
    printf("Unmapping Failed\n");
    return 1;
  }
  return 0;
}

출력:

Initial array's values: 7 8 9 10 11
Initial array's values: 7 8 9 10 11

Parent:
Updated array's values: 35 40 45 50 55

처음에 일부 값으로 배열을 초기화합니다. 그런 다음 자녀의 프로세스가 값을 변경합니다.

또한 매핑된 메모리가 두 (자식 및 부모) 프로세스와 공유되기 때문에 자식 프로세스에 의해 변경된 값은 부모 프로세스에서 읽습니다. 우리는 또한 메모리 매핑을 제거하기 위해 munmap()을 사용하고 있습니다.

Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

관련 문장 - C Function