공유 메모리는 Linux/UNIX 운영체제에서 프로세스 간 데이터 공유를 위한 메커니즘 중 하나이다.
공유 메모리를 사용하는 주된 사용 용도는 다음과 같다.
공유 메모리를 사용하기 위해선 가장 먼저 생성된 key를 통해 shmget()
함수를 사용하여 공유 메모리를 생성하고 공유 메모리를 사용할 프로세스에서 shmat()
함수를 통해 메모리에 attach해야 한다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PRO_IDFR "/home/projects/memoryTest"
#define SHM_SIZE 1024
int main() {
key_t key = ftok(PRO_IDFR, 'ShmKey');
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(EXIT_FAILURE);
}
char *shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (char *)-1) {
perror("shmat");
exit(EXIT_FAILURE);
}
// 공유 메모리에 데이터 쓰기
sprintf(shmaddr, "Hello, Shared Memory!");
// 다른 프로세스에서 공유 메모리 읽기
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid > 0) {
// 부모 프로세스에서 읽기
printf("Parent Process: %s\n", shmaddr);
exit(EXIT_SUCCESS);
}
if (pid == 0) {
// 자식 프로세스에서 읽기
printf("Child Process: %s\n", shmaddr);
exit(EXIT_SUCCESS);
}
// 공유 메모리 분리
if (shmdt(shmaddr) == -1) {
perror("shmdt");
exit(EXIT_FAILURE);
}
// 공유 메모리 제거
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
exit(EXIT_FAILURE);
}
delete shmaddr;
return 0;
}
코드를 해석하면 다음과 같다.
1. 공유 메모리를 생성한다.
- shmget()
함수를 통해 공유 메모리를 생성한다.
- 사전에 생성한 key와 define된 사이즈를 매개 변수로 사용하였다.
- IPC_CREAT
플래그는 해당 키에 해당하는 공유 메모리 영역이 없으면 새로 생성하라는 의미이다. 만약 키에 해당하는 공유 메모리 영역이 이미 존재한다면, 이 플래그는 무시된다.
- 0666
플래그는 생성된 공유 메모리 영역에 대한 퍼미션(권한)을 지정한다. 0666은 읽기와 쓰기 권한을 부여하는 값으로, 소유자, 그룹, 다른 사용자에 대해 모든 권한이 부여된다.
- IPC_CREAT
플래그 값은 01000이므로, 최종적으로 OR 연산에 의해 플래그는 01666
이 된다.
2. 공유 메모리를 연결(attach)한다.
- shmat()
함수를 통해 공유 메모리를 연결한다.
- 첫 번째 매개변수는 연결하려는 공유 메모리 영역의 식별자(ID)이다. shmget()
함수를 통해 공유 메모리 영역을 생성하는데 사용된 ID를 사용해야 생성된 공유 메모리 영역에 연결할 수 있다.
- shmaddr
은 연결하려는 공유 메모리를 현재 프로세스의 주소 공간에 어디에 붙일지를 지정한다. 보통 NULL을 사용하면 시스템이 알아서 적절한 주소를 선택한다.
- shmflg
는 공유 메모리에 대한 플래그를 지정한다. 특별한 설정이 필요하지 않다면 0을 사용한다.
3. 공유 메모리를 분리한다
- shmdt()
함수를 통해 연결된 공유 메모리를 분리한다.
4. 공유 메모리를 제거한다.
- shmctl()
함수를 통해 공유 메모리를 제거한다.
- shmctl()
함수는 공유 메모리 식별자에 대한 제어 연산을 수행하는 함수이다.
- 첫 번째 매개 변수 shmid
는 공유 메모리 식별자를 나타낸다.
- 두 번째 매개 변수 cmd
는 수행할 제어 명령을 나타낸다. IPC_RMID
는 공유 메모리 세그먼트를 제거하는데 사용된다.
- 세 번째 매개 변수는 struct shmid_ds *
타입으로 되어 있으며 이 구조체는 공유 메모리의 상태 정보를 저장한다. 일반적으로는 NULL을 사용한다.