shmat(2)

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

void *shmat(int shmid, const void *shmaddr, int shmflg);

shmat(2)는 shmid에 mapping된 System V shared memory segment를 C언어의 pointer 변수에 attach하는 함수입니다.

 

return되는 attach할 memory 주소는 shmaddr에 의해서 정해집니다.

shmaddr이 NULL이면 system이 사용하지 않는 적당한 주소에 attach하여 return합니다.

shmaddr이 NULL이 아니고 shmflg가 SHM_RND이면, shmaddr이 SHMLBA의 배수이면 shmaddr에 그렇지 않으면 shmaddr보다 작은 주소 중에서 SHMLBA의 배수인 가장 가까운 memory 번지에 attach됩니다. 그렇지 않으면, page의 시작 위치 주소에 attach됩니다.

 

shmflg가 SHM_RDONLY이면, shared memory segment는 읽기 전용으로 메모리가 attach됩니다. 그렇지 않으면 shared memory segment에 대해서 read / write가 가능하도록 attach됩니다. 쓰기 전용으로는 attach될 수 없습니다.

 

fork(2)된 child는 attach된 메모리를 공유합니다. execve(2)를 호출하면 자동으로 detach됩니다. 프로세스가 종료되면 자동으로 attach된 pointer는 detatch됩니다. 

 

 

파라미터

shmid
    - shmget(2)함수에 의해서 return된 shared memory segment id
shmaddr
    - attach될 메모리 주소 값을 설정합니다. 
    - shmflg의 값과 shmaddr 주소값에 의해서 attach된 주소를 return합니다.(설명 참조)
shmflg
    - SHM_RND, SHM_RDONLY 또는 0을 설정합니다. (설명 참조)

 

RETURN

(void *) -1이 아님
    - 정상적으로 attach된 메모리 번지 값

  정상적으로 shmat()호출되면 shmctl(2)에 의해서 얻는 shmid_ds 구조체의 아래 항목의 값을 갱신합니다.
  - shm_atime 를 현재시간으로 갱신합니다.
  - shm_lpid를 현재 process id로 갱신합니다.
  - shm_nattch 값을 1증가시킵니다.

(void *) -1
    - 오류가 발생하였으며, 상세 오류 내용은 errno 전역변수에 설정됩니다.

 EACCES : 접근권한이 없습니다. shmget(2)함수에서 설정한 권한이 shmat(2)함수를 호출한
          process를 실행한 user에게 권한이 없습니다.
 EIDRM  : shmid가 삭제된 id입니다.
 EINVAL : shmid가 유효하지 않거나 shmaddr이 유효하지 않습니다.
     또는 shmaddr에 segment를 attach할 수 없거나, shmflg가 SHM_REMAP으로 설정되었는 데, 
     shmaddr값이 NULL입니다.
 ENOMEM : memory를 할당할 수 없습니다.

 


활용 예제

 

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

......

int main(int argc, char **argv)
{
    int     shmid;
    int     mem_size;
    key_t   shm_key;
    struct  my_data_t *shm_data;

    ......

    /* shared memory용 IPC key를 생성함 */
    if((shm_key = ftok("~/mywork", 'H')) == -1) {
        perror("shared memory key 생성 오류");
        return 1;
    }

    mem_sie = sizeof(struct my_data_t) * 1000;
    shmid = shmget((key_t)shm_key, mem_size, 0600 | IPC_CREAT);

    if (shmid == -1) {
        perror("shmget failed ");
        return 1;
    }

    /* 생성된 shared memroy를 참조함 */
    shm_data = shmat(shmid, (void *)0, 0);

    if (shm_data == (void *)-1) {
        perror("shmat failed ");
        return 1;
    }

    ......

    return 0;
}

 

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

댓글을 달아 주세요