shm_open을 동일한 이름으로 두 번 호출하면 같은 메모리인가요?
shm_open을 동일한 이름으로 두 번 호출하면 같은 메모리인가요?
POSIX 공유 메모리(shm_open)를 처음 사용하는 많은 개발자들이 갖는 궁금증 중 하나는, “동일한 이름으로 shm_open()을 여러 번 호출하면 각각 다른 메모리를 사용하는가?” 입니다. 또한, mmap()을 통해 매핑할 경우 가상 주소도 동일한지에 대해 혼동되는 경우가 많습니다.
이번 글에서는 shm_open을 동일한 이름으로 두 번 호출한 뒤 mmap()으로 매핑하고, 두 포인터가 실제로 같은 공유 메모리를 바라보는지 여부를 실험을 통해 살펴보겠습니다.
실험 목적
shm_open()을 같은 이름으로 두 번 호출하면 실제로 같은 공유 메모리를 사용하는지 확인- 각각의
mmap()결과 주소가 동일한지 확인 - 두 포인터를 통해 데이터를 공유할 수 있는지 테스트
실험 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
int main() {
const char* shm_name = "/shm_test";
const size_t size = 4096;
// 첫 번째 shm_open
int fd1 = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
ftruncate(fd1, size);
void* addr1 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
close(fd1);
// 두 번째 shm_open
int fd2 = shm_open(shm_name, O_RDWR, 0666);
void* addr2 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
close(fd2);
// 공유 여부 테스트
strcpy((char*)addr1, "공유 메모리 테스트");
printf("addr1: %p, 내용: %s\n", addr1, (char*)addr1);
printf("addr2: %p, 내용: %s\n", addr2, (char*)addr2);
// 정리
munmap(addr1, size);
munmap(addr2, size);
shm_unlink(shm_name);
return 0;
}
🧪 실험 결과
1
2
addr1: 0x7f1b02b00000, 내용: 공유 메모리 테스트
addr2: 0x7f1b02d00000, 내용: 공유 메모리 테스트
출력 결과를 보면 두 포인터(addr1, addr2)는 서로 다른 주소를 가리키고 있지만, 그 내부에 담긴 문자열은 동일하게 ‘공유 메모리 테스트’로 출력되고 있습니다.
이는 두 포인터가 같은 공유 메모리 객체를 매핑받았다는 의미입니다. 즉, shm_open()을 동일한 이름으로 두 번 호출하면 같은 커널 메모리 객체를 참조하게 되며, mmap()은 이를 각각의 프로세스 주소 공간 내 다른 위치에 매핑해주는 것입니다.
📊 분석 및 결론
| 질문 | 결과 |
|---|---|
동일한 이름으로 shm_open() 두 번 호출하면? | ✔️ 같은 공유 메모리 객체를 엽니다 |
mmap() 결과 주소는 동일한가요? | ❌ 아닙니다. 각자 다른 가상 주소에 매핑됩니다 |
| 두 주소는 같은 물리 메모리를 참조하나요? | ✔️ 네, 같은 커널 메모리 객체를 공유합니다 |
| 데이터는 공유되나요? | ✔️ 완전히 동일한 데이터를 참조하며 공유됩니다 |
🔍 추가 설명
shm_open()은 이름 기반으로 커널 수준에서 공유 메모리 객체를 생성하거나 참조합니다. 동일한 이름을 사용하면 같은 메모리 객체를 여러 핸들로 열 수 있습니다.mmap()은 가상 주소 공간에 메모리를 매핑하는 함수입니다. 같은 공유 메모리 객체라도 호출 시점마다 가상 주소는 달라질 수 있습니다. 이는 커널이 비어 있는 주소 영역에 자동으로 배치하기 때문입니다.하지만 mmap의 목적은 가상 주소를 통해 같은 물리 메모리에 접근하는 것이므로
addr1과addr2는 주소는 다르지만 결국 같은 메모리 페이지를 바라보고 있게 됩니다.
⚠️ 주의사항
mmap()의 첫 번째 인자에 원하는 주소를 명시하고MAP_FIXED를 사용하면 강제로 특정 주소에 매핑할 수 있지만, 해당 주소가 이미 사용 중일 경우 프로세스가 크래시 날 수 있어 권장되지 않습니다. 따라서 특별한 이유가 없다면 커널이 적절한 주소를 선택하도록 두는 것이 안전합니다.공유 메모리 사용 후에는 반드시
munmap()과shm_unlink()로 정리해주는 것이 좋습니다.
마무리
shm_open()은 동일한 이름을 사용할 경우 동일한 커널 객체를 반환합니다.mmap()주소는 달라도 물리 메모리는 공유됩니다.공유 메모리를 테스트할 때는 주소 비교보다 실제 데이터 공유 여부를 확인하세요.