블로그는 나의 힘!
[ Programing ]/Server2010. 7. 23. 21:22

요약 : 다중처리 시스템에서, 여러 개의 프로세서가 공동으로 사용하는 주기억장치를 말한다.
 
 
 
1. 텀즈 코리아

컴퓨터 프로그래밍에서,
공유 메모리는 일반 운영체계 서비스가 사용하는 읽기/쓰기 방식에 의한 것보다 프로그램 프로세스들이 데이터를 더 빠르게 교환할 수 있는 방법이다.
 
클라이언트 프로세서가 전달한 데이터를, 서버 프로세스가 수정 후 다시 클라이언트에게 되돌려주는 경우를 생각해 보자.
대개, 이런 경우에는 클라이언트가 운영체계의 버퍼를 사용하여 출력 파일에 기록하면, 서버는 버퍼로부터 그 파일을 자신의 작업 공간 내로 읽어들이게 된다.
 
그러나, 공유 메모리의 지정된 공간을 사용하면, 시스템 서비스를 사용하지 않고서도 데이터가 양쪽 프로세스에 의해 직접 액세스될 수 있도록 만들어질 수 있다.
데이터를 공유 메모리에 집어넣기 위해, 클라이언트는 세마포어 값을 확인한 후에 공유 메모리에 액세스하여 데이터를 기록하며, 그 다음에 대기하고 있는 데이터가 있다는 사실을 서버에게 알려주기 위해 세마포어 값을 재설정한다.
(서버는 공유 메모리에 입력 데이터가 있는지를 알기 위하여 세마포어 값을 주기적으로 확인한다)
 
차례대로,
서버 프로세스는 공유 메모리 공간에 데이터 다시 기록하고, 세마포어 사용하여 데이터 읽혀질 준비 되었다는 사실을 알린다.


 
 
2.  네이버 지식인
 
한 개의 메모리를 여러 처리장치(프로세서)가 공동으로 사용하는 형태의 기억장치 또는 다중처리(multiprocessing) 시스템을 사용할  때,  여러 프로세서가 하나의 기억장치를 공유하여 사용하는 것을 의미한다. 

여러 처리장치가 동시에 하나의 기억장치를 사용하므로
한 장소를 중복하여 사용되는 경우가 생길 수 있으므로 이런 현상을 방지하기 위해 사용시간을 잘 배분하는 복잡한 제어가 필요하다.
 
공유메모리에 기록된 내용을 여러 처리장치가 자유롭게 할 수 있지만, 기록하는 경우에는 문제가 발생할 수 있기 때문에 제한을 두어 관리하는 것이다
이에 비해 시분할처리 시스템에서 중앙의 연산장치가 여러 개의 기억장치를 갖추어 데이터 처리를 하는 것을 공유 프로세서라고 한다.

 
 
 
3. Joinc Wiki
 
* 관련 함수
#include <sys/types.h>
#include <sys/shm.h>

 
// 커널에 공유메모리 공간을 요청하기 위해 호출하는 시스템 호출 함수
// 1인자 : 여러개의 공유메모리중 원하는 공유메모리에 접근하기 위한 Key,
//            Key 값은 커널에 의해서 관리, Key 값을 통해서 선택적인 공유메모리에의 접근이 가능
// 2인자 : 공유메모리의 최소크기. 존재하는 메모리를 참조한다면 크기는 0으로 명시
// 3인자 : 공유메모리의 접근권한과, 생성방식을 명시. 생성방식을 지정하기 위해 IPC_CREAT, IPC_EXCL 사용
//         IPC_CREAT = key 이용 새로운 공유메모리 공간을 만든다.
//         IPC_EXCL = IPC_CREAT와 같이 사용, 공유메모리 공간이 이미 존재할경우 error 반환

int shmget(key_t key, int size, int shmflg)
 
// 공유메모리 공간을 생성했으면, 공유메모리에 접근할수 있는 int 형의 "식별자" 를 얻게 된다.
// shmat 이용해 프로세스가 공유메모리를 사용 허용.
// 1인자 : shmget 이용해 얻어낸 식별자 번호
// 2인자 : 메모리가 붙을 주소를 명시위해 사용, 0 사용할 경우 커널이 메모리가 붙을 주소를 명시. 
//           특별한 사항이 없다면 0을 사용
// 3인자 : 해당 공유메모리에 대한 "읽기전용", "읽기/쓰기가능" 모드 열수 있음.
//         SHM_RDONLY = 지정할 경우 읽기 전용.
//         NULL = 아무값도 지정하지 않을경우 "읽기/쓰기 가능" 모드.

void *shmat( int shmid, const void *shmaddr, int shmflg )
 
// 프로세스가 더이상 공유메모리를 사용할필요가 없을경우 프로세스와 공유메모리를 분리 하기 위해서 사용.
// 단지 현재 프로세스와 공유메모리를 분리시킬뿐, 공유메모리 내용을 삭제하지는 않는다.
// 공유메모리를 커널상에서 삭제 시키길 원한다면 shmctl 같은 함수를 이용.

int shmdt( const void *shmaddr)
 
// 공유메모리를 제어하기 위해서 사용.
// 1인자 : shmget 이용해 얻어낸 식별자 번호
// 2인자 : shmid 가 가르키는 공유메모리를 제어, cmd 를 이용해서 원하는 제어
//         IPC_STAT = 공유메모리 공간에 관한 정보를 가져오기 위해서 사용. 정보는 buf 에 저장.
//         IPC_SET = 공유메모리 공간에 대한 사용자권한 변경을 위해서 사용.
//                         사용자 권한 변경 위해서는 슈퍼유저 혹은 사용자권한을 가져야 함.
//         IPC_RMID = 공유메모리 공간을 삭제하기 위해서 사용.
//                          공간을 사용하는 프로세스가 없을때, 즉 shm_nattch 가 0일때 까지 기다렸다가 삭제.

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

* 관련 구조체

struct shmid_ds
{
   struct ipc_perm shm_perm;   // 퍼미션
   int shm_segsz;                  // 메모리 공간의 크기
   time_t shm_dtime;                // 마지막 attach 시간
   time_t shm_dtime;                // 마지막 detach 시간
   time_t shm_ctime;                // 마지막 변경 시간
   unsigned short shm_cpid;     // 생성프로세스의 pid
   unsigned short shm_lpid;      // 마지막으로 작동한 프로세스의 pid
   short shm_nattch;                // 현재 접근한 프로세스의 수
};
 
* 권한 지정
int shmid;
key_t keyval;

keyval = 1234;
shmid = shmget(keyval, 1024, IPC_CREAT | 0666)); 
if (shmid == -1)
{
    return -1;
}
 
* 예제
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <unistd.h> 

int main()
{
    int shmid;
    int pid; 
    int *cal_num;
    void *shared_memory = (void *)0; 

    // 공유메모리 공간을 만든다.
    shmid = shmget((key_t)1234, sizeof(int), 0666|IPC_CREAT); 

    if (shmid == -1)
    {
        perror("shmget failed : ");
        exit(0);
    } 

    // 공유메모리를 사용하기 위해 프로세스메모리에 붙인다. 
    shared_memory = shmat(shmid, (void *)0, 0);
    if (shared_memory == (void *)-1)
    {
        perror("shmat failed : ");
        exit(0);
    } 

    cal_num = (int *)shared_memory;
    pid = fork();
    if (pid == 0)
    {
        shmid = shmget((key_t)1234, sizeof(int), 0);
        if (shmid == -1)
        {
            perror("shmget failed : ");
            exit(0);
        }
        shared_memory = shmat(shmid, (void *)0, 0666|IPC_CREAT);
        if (shared_memory == (void *)-1)
        {
            perror("shmat failed : ");
            exit(0);
        }
        cal_num = (int *)shared_memory;
        *cal_num = 1; 

        while(1)
        {
            *cal_num = *cal_num + 1;
            printf("child %d\n", *cal_num); 
            sleep(1);
        }
    } 

    // 부모 프로세스로 공유메모리의 내용을 보여준다. 
    else if(pid > 0)
    {
        while(1)
        {
            sleep(1);
            printf("%d\n", *cal_num);
        }
    }

 
* /proc 파일 시스템으로 제어하기
: 리눅스 운영체제는 /proc 파일 시스템으로 공유 메모리 자원 값을 변경할 수 있다. 
  /proc/sys/kernel/shmmax : 프로세스가 생성할 수 있는 공유 메모리의 최대 크기
  /proc/sys/kernel/shmall : 현재 사용중인 공유 메모리 크기

: 프로세스가 생성할 수 있는 공유 메모리 크기는 다음과 같이 변경하면 된다.
// 500M로
# echo 536870912 > /proc/sys/kernel/shmmax
 
 

'[ Programing ] > Server' 카테고리의 다른 글

뮤텍스와 세마포어  (0) 2013.08.22
이벤트 객체 CreateEvent, SetEvent, ResetEvent, PulseEvent  (0) 2012.12.04
메모리 락  (0) 2010.06.29
POSIX 정규 표현식  (0) 2010.06.29
Mutex 설정  (0) 2010.06.16
Posted by Mister_Q