Shared Memory

POSIX Standard에서 제공하는 api함수를 이용하여 공유 메모리를 설정하고 이용할 수 있다.
먼저 man page는 다음과 같다.

manual page에 자세하게 설명되어 있듯이, shm_open을 사용하기 위해서는 먼저, 헤더 #include <sys/mman.h> 가 필요하다.
그 다음에, mode flag와 open option을 이용하기 위해서,
#include <sys/stat.h>
#include <fcntl.h> 가 필요하다.

shm_open을 실제로 이용한 예제는 다음과 같다.

코드 라인 12 ~ 21 까지의 구조체는 공유메모리 영역에서 관리될 자료구조이다.
메인함수 내에서 라인 28~31을 보면,
const int SIZE = sizeof( banker );
로 되어있는 부분은 공유메모리 영역에서 관리될 구조체의 전체 크기이다.
const char *name = “/banker”;
는 공유메모리의 이름이다.
POSIX에서는 이 공유메모리의 이름으로 접근할 수 있게 된다.

*주의해야 할 부분은 const 로 선언된 부분은 이 공유메모리를 같이 이용할 다른 프로세스에서도 똑같이 적용되어야 한다는 것이다.
공유메모리의 이름이 다르거나, 혹은 사이즈가 다르면 공유메모리에 접근할 수 없으니 유의해야 한다.

*또한, 공유메모리의 이름을 설정하는 부분에서, linux에서는 이름 앞에 / 없이도 공유메모리를 사용할 수 있다.
(manual page에서는 권장하고 있지 않지만, operating system concepts 교재의 예제에서 / 없이 사용하고 있다.)
하지만 solaris(sun)에서는 반드시 /를 붙여야 합니다. 그렇지 않으면 반드시 core dump error를 맞이하게 되니 주의해야 한다.

int shm_fd 를 선언하여 shm_open을 한다.
shm_opem의 파라미터를 보면,
int shm_open(공유메모리 이름, open_flag, 접근 권한);
로 되어있으며, 성공시에는 file descriptor를 return하게 된다.

다음의 ftruncate는 실제 공유되고 있는 메모리 사이즈만큼으로 shm_fd의 크기를 조절해 준다.
그 다음 45번 라인이 공유메모리를 사용하는 핵심적인 부분이라 할 수 있다.
예시로 사용된 코드에서는, 공유될 자료들의 구조체 이름이 banker 이다.
따라서, banker 형 포인터 p를 사용하도록 한다.
이 포인터 p에다가 공유 메모리의 주소를 assign하여 코드에서 사용할 것이다.
여기에 필요한 함수가 mmap() 함수이다.
이 함수 역시 #include <sys/mman.h> 에 정의되어 있다.
원형은 다음과 같다.
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
따라서 예시의 코드에서는,
mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
으로 작성되고, return type이 void 형이기 때문에, 앞에 (banker *)로 typecast를 해주었다.
(형변환을 하지 않아도 사용할 수 있으나, 컴파일 시에 warning이 발생하게 됩니다.)
mmap의 파라미터에 대해서는 man page를 참조하면 자세하게 알 수 있다.
mapping이 성공하게 되면, mmap은 공유메모리의 포인터를 리턴하게 된다.

이로써 공유메모리를 사용할 모든 준비가 끝났다.
사용할 때에는 일반 포인터를 사용하듯 사용하면 된다.
예를 들어,
p->available[0] = 1;
과 같이 사용하면 된다.

*공유메모리를 모두 사용하고 나서는 반드시
munmap((void *)pointer, size_t SIZE);
shm_unlink(name);
를 해서 unmapping과 unlink를 해야 한다.
그렇지 않으면, 프로세스는 종료되어도 메모리 상에 공유메모리 영역이 제거되지 않을 수 있다.
그러면 같은 프로세스를 다시 시작할 때, 정상적으로 작동하지 않을 수 있다.

마지막으로, 컴파일 시에는 옵션으로 꼭 -lrt 를 해 주어야만 한다.
-lrt를 적지 않으면 컴파일 에러가 발생하게 된다.
ex) gcc -o a.out test.c -lrt

댓글 남기기