본문 바로가기

Computer Science/Note

공유메모리와 관련 함수

728x90

공유메모리와 관련 함수

1. 프로세스와 메모리

  모든 프로세스는 자신의 업무를 수행하기 위해서 필요한 자료를 저장하기 위해 각자 메모리공간을 차지한다.

이러한 메모리공간에는 CPU에 의해 수행되는 명령어들, 프로그램 시작시 정의되고 초기화된 데이타, 프로그램 시작시 정의되었지만 초기화 되지 않은 데이타, 함수호출에 필요한 정보, 동적할당이 이루어지는 데이타등 이 들어간다.


  프로세스는 시작시 혹은 실행중에 이러한 데이타를 저장하고 사용하기 위한 메모리 공간을 커널에 요구하여서 할당받아 사용하게 되는데, 이러한 메모리공간은 기본적으로 메모리를 요청한 프로세스만이 접근가능하도록 되어있다.


  하지만 가끔은 여러개의 프로세스가 특정 메모리 공간을 동시에 접근해야할 필요성을 가질때가 있을것이다.


2. 공유메모리

  모든 프로세스는 각자 자신의 업무수행만을 위한 메모리공간을 차지하게 되는데, 여러개의 프로세스가 특정한 메모리영역을 동시에 접근해야할 경우가 있다. 이때 여러 프로세스가 동시에 접근하고 사용하게 되는 메모리를 공유메모리라 한다.

  공유메모리는 여러 IPC 중에서 가장 빠른 수행속도를 보여준다. 그이유는 하나의 메모리를 공유해서 접근하게 되므로, 데이타 복사와 같은 불필요한 오버헤드가 발생하지 않기 때문으로, 빠른 데이타의 이용이 가능하다.


3. 공유메모리과 관련있는 함수들

다음은 공유메모리에 관련된 함수들이다.

#include <sys/types.h>
#include <sys/shm.h>

int shmget(key_t key, int size, int shmflg)
int shmat ( int shmid, char *shmaddr, int shmflg);
int shmdt( const void *shmaddr)
int shmctl(int shmid, int cmd, struct shmid_ds *buf)


4. 공유메모리의 생성과 접근 과정

(1)공유메모리 생성과 관리

  공유메모리의 생성요청은 최초 공유메모리 영역을 만드는 프로세스가 커널에 공유메모리 공간의 할당을 요청함으로써 이루어지며, 만들어진 공유메모리는 커널에 의해서 관리 되게 된다.

  이런 이유로 한번만들어진 공유메모리는 운영체제를 리부팅하거나, 직접 공유메모리 공간을 삭제시켜주지 않은한, 공유메모리를 사용하는 모든 프로세스가 없어졌다고 하더라도, 계속적으로 유지되게 된다.

  프로세스가 커널에게 공유메모리 공간을 요청하게 되면, 커널은 공유메모리 공간을 할당 해주고, 내부자료구조를 통하여 공유메모리를 관리한다.

(2)공유메모리에의 접근

  공유메모리가 할당되면 key값이 정해진다. 공유메모리에 접근을 하기 위해서는 고유의 공유메모리 key값을 이용하고, 또 이 key값으로인해 통해서 다른 여러개의 공유메모리들과 구분되어 질수 있다.


5. 공유메모리 관련 함수 설명

(1)shmget

int shmget(key_t key, size_t size, int shmflg);

  shmget은 커널에 key를 접근번호로 하는 공유메모리 공간을 요청하고 공유메모리를 가르키는 식별자를 리턴해주는 함수이다. shmget 을 이용해서 새로운 공유메모리 영역을 생성하거나 기존의 공유메모리 영역을 참조할수 있다. 커널에서 성공적으로 공유메모리 공간을 할당하게 되면공유메모리를 가르키는 int형 식별자를 리턴하게 된다.

  두번째의 size에서는 byte단위로 공유메모리의 최소크기를 지정할 수 있다. 새로운 공유메모리를 생성하고자 한다면 크기를 명시해주어야 한다. 존재하는 메모리를 참조한다면 크기는 0으로 명시한다.

  세번째 shmflg는 공유메모리의 접근권한과, 생성방식을 명시하기 위해서 사용한다. 
아규먼트의 생성방식을 지정하기 위해서 IPC_CREAT 와 IPC_EXCL 을 사용할수 있다. 아래 이들에 대해서 설명을 해두었다.

IPC_CREAT 
key 를 이용 새로운 공유메모리 공간을 만든다. 

IPC_EXCL 
IPC_CREAT와 같이 사용(ex. IPC_CREAT | IPC_EXCL | 0666의 형태로..)되며, 공유메모리 공간이 이미 존재할경우 error가 발생하여 -1 을 되돌려준다.

  만약 IPC_CREAT 만 사용된다면 shmget()은 새로 생성되는 공유메모리공간을 지시하는 공유메모리공간 "식별자" 되돌려준다. 만약 입력된 key 값이 지시하는 공유메모리 공간이 이미 존재하고 있다면 존재하는 공유메모리 공간의 "식별자"를 되돌려준다. IPC_EXCL 과 IPC_CREAT 를 같이 사용할경우, 공유메모리 공간이 존재하지 않으면 새로 생성시켜주며, 존재할경우에 error를 되돌려준다.

  shmflg에서는 이외에도 권한을 지정해줄수도 있다. 권한은 파일권한과 동일하게, 유저, 그룹, Other 에 대한 읽기/쓰기 권한을 지정할수 있다. 단 실행권한은 줄수 없도록 되어 있다.

(2)shmat

int shmat(int shmid, char *shmaddr, int shmflg);

  공유메모리 공간을 생성(shmget)했으면, 공유메모리에 접근할수 있는 int형 식별자(공유메모리를 가르키는 식별자)를 얻게 된다. shmat함수는 이 int형 식별자를 이용해서 지금의 프로세스가 공유메모리를 사용가능하도록 "덧붙임" 작업을 하고, 식별자에 해당하는 공유메모리의 주소를 리턴해준다.

  첫번째 shmid는 shmget을 이용해서 얻어낸 식별자를 의미한다.
  두번째 *shmaddr은 메모리가 붙을 주소를 명시하기 위해 사용하는데, 0을 사용할경우 커널이 메모리가 붙을 주소를 명시하게 된다. 특별한 사항이 없다면 0을 사용하도록 한다.
  세번째 shmflg는, 해당 공유메모리를 "읽기전용", "읽기/쓰기 가능" 모드로 열수 있는데, SHM_RDONLY로 하면 읽기전용, 아무값도 지정하지 않을경우(0 혹은 NULL) "읽기/쓰기 가능" 모드로 열리게 된다.

(3)shmdt

int shmdt( const void *shmaddr)

  프로세스가 더이상 공유메모리를 사용할필요가 없을경우 프로세스와 공유메모리를 분리 하기 위해서 사용한다. 이 함수를 호출할 경우 단지 현재 프로세스와 공유메모리를 분리시킬뿐이지, 공유메모리 내용을 삭제하지는 않는다는 점을 기억해야 한다. 
공유메모리를 커널상에서 삭제 시키길 원한다면 shmctl 같은 함수를 이용해야 한다.

  shmdt 가 성공적으로 수행되면 커널은 shmid_ds 의 내용을 갱신한다.
  즉 shm_dtime, shm_lpid, shm_nattch 등의 내용을 갱신하는데, shm_dtime 는 가장 최근에 dettach (즉 shmdt 를 사용한)된 시간, shm_lpid 는 호출한 프로세세의 PID, shm_nattch 는 현재 공유메모리를 사용하는 (shmat 를 이용해서 공유메모리에 붙어있는) 프로세스의 수를 돌려준다. shmdt 를 사용하게 되면 shm_nattch 는 1 감소하게 될것이며, shm_nattch 가 0 즉 더이상 붙어있는 프로세스가 없다라는 뜻이 될것이다. shm_nattch 가 0이 되어있을때 만약 이 공유메모리가 shm_ctl 등에 의해 삭제표시 가 되어 있다면, 이 공유메모리는 삭제되게 된다.

(4)shmctl

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

  이것은 공유메모리를 제어하기 위해서 사용한다. 
  즉 shmid_ds 를 직접 제어함으로써, 해당 공유메모리에 대한 소유자, 그룹 등의 허가권을 변경하거나, 공유메모리를 삭제혹은, 공유메모리의 잠금을 설정하거나 해제하는 등의 작업을 한다.

  두번째 아규먼트를 이용해서 shmid가 가르키는 공유메모리를 제어하며, cmd를 이용해서 원하는 제어를 할수 있다. cmd를 이용해 내릴수 있는 명령에는 다음과 같은 것들이 있다.

IPC_STAT 
공유메모리 공간에 관한 정보를 가져오기 위해서 사용된다. 정보는 buf 에 저장된다.

IPC_SET 
공유메모리 공간에 대한 사용자권한 변경을 위해서 사용된다. 사용자 권한 변경을 위해서는 슈퍼유저 혹은 사용자권한을 가지고 있어야 한다. 

IPC_RMID 
공유메모리 공간을 삭제하기 위해서 사용된다. 이 명령을 사용한다고 해서 곧바로 사용되는건 아니며, 더이상 공유메모리 공간을 사용하는 프로세스가 없을때, 즉 shm_nattch 가 0일때 까지 기다렸다가 삭제된다. 즉 해당 공유메모리 공간에 대해서 삭제표시를 하는거라고 생각하면 된다. 



출처:http://geundi.tistory.com/52