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)
이 함수를 사용하기 전에 인수에 대해 논의해 봅시다.
-
주소
- 매핑에 사용되는 기본 시작 주소를 제공합니다. 다른 매핑이 없으면 커널은 가까운 페이지 경계를 선택하여 매핑을 생성합니다.그렇지 않으면 커널이 새 주소를 선택합니다. 이 매개변수의 값이
NULL
인 경우 커널은 적절하다고 판단되는 위치에 매핑을 배치합니다. -
길이
- 바이트 수가 매핑됩니다. -
보호
- 허용되는 액세스 유형을 제어합니다. 예를 들어, 읽기 액세스를 위한PROT_READ
, 쓰기 액세스를 위한PROT_WRITE
, 실행을 위한PROT_EXEC
입니다. -
플래그
- 맵의 특성을 제어하는 데 사용됩니다. 일반적이고 유용한 플래그 중 일부는 다음과 같습니다.MAP_SHARED
- 다른 프로세스와 매핑을 공유합니다.MAP_FIXED
- 시스템은address
매개변수를 통해 제공된 동일한 매핑 주소를 사용하도록 강제됩니다.MAP_ANONYMOUS / MAP_ANON
- 익명 매핑을 생성합니다.MAP_PRIVATE
- 이 플래그를 사용하는 동안 매핑은 비공개이며 다른 사람에게 표시되지 않습니다.
-
filedes
- 파일 설명자는 매핑되어야 합니다. -
오프셋
- 파일 매핑이 이 오프셋에서 시작됩니다.
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()
을 사용하고 있습니다.