/** @file sharemem.c @date 2006 @author 유영창 frog@falinux.com FALinux.Co.,Ltd. @author 오재경 freefrug@falinux.com FALinux.Co.,Ltd. @brief 공유메모리를 생성하고 해제한다. @modify @todo @bug @remark @warning */ // // 저작권 에프에이리눅스(주) // 외부공개 금지 // //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include /// 공유메모리 관리를 위한 구조체 typedef struct { int key; // 사용자가 바라보는 식별자 int id; // 공유메모리 핸들 char data[0]; // 사용자가 엑세스하는 메모리 } share_t; //------------------------------------------------------------------------------ /** @brief 공유메모리를 삭제한다. @param key 공유메모리를 지정하는 유니크값 @remark *///---------------------------------------------------------------------------- void share_delete( int key ) { FILE *fp; char line[128]; int id = -1; int size; // shm 정보파일을 연다. fp = fopen( "/proc/sysvipc/shm", "r" ); if(fp == NULL) return; // 첫번째 라인 무시 fgets( line, sizeof(line), fp ); while(1) { int tmp_key, tmp_id, tmp_perm, tmp_size; if ( fgets( line, sizeof(line), fp ) == NULL ) break; // 키값과 크기를 읽어온다. if ( sscanf( line, "%d %d %d %d", &tmp_key, &tmp_id, &tmp_perm, &tmp_size ) == 4 ) { // printf( "SHM KEY = %d ID = %d SIZE=%d\n", tmp_key, tmp_id, tmp_size ); if ( tmp_key == key ) { id = tmp_id; // 해당하는 id 를 찾았다 size = tmp_size; break; } } } // 파일을 닫는다. fclose( fp ); // id 를 찾았다면 공유메모리를 삭제한다. if( id >= 0 ) { id = shmget( key, size, 0666 | IPC_CREAT); shmctl( id, IPC_RMID, NULL ); } } //------------------------------------------------------------------------------ /** @brief 공유 메모리를 생성한다. @param key 공유메모리를 지정하는 유니크값 @param size 생성할 공유메모리 크기 @return 할당받은 공유메모리 @remark *///---------------------------------------------------------------------------- void *share_create( int key, unsigned int size ) { int id; void *ptr; share_t *share; // printf( "share_create key = %d\n" , key ); // 공유 메모리를 생성하여 핸들을 얻거나 이미 있으면 해당 핸들을 가져 온다. id = shmget( key, sizeof(share_t) + size, 0666 | IPC_CREAT ); // printf("shmget id = %d\n", id ) if( id < 0 ) { // 만약에 기존에 다른 크기로 생성되어 있다면 // 이전것을 모두 삭제 처리 하고 재 생성을 요청한다. // printf("Exit Share Memory %08X\n", key ); share_delete( key ); // 다시 할당받는다. id = shmget( key, size + sizeof(share_t), 0666 | IPC_CREAT | IPC_EXCL ); if( id < 0 ) return NULL; } // 공유메모리의 선두 주소를 얻어온다. ptr = shmat( id, NULL, 0 ); if( ptr == NULL ) return NULL; // 공유메모리의 정보를 저장한다. share = (share_t *) ptr; share->key = key; share->id = id; return share->data; } //------------------------------------------------------------------------------ /** @brief 공유 메모리를 해제한다. @param data share_create() 함수로 받은 메모리 포인터 @remark *///---------------------------------------------------------------------------- void share_free( void *data ) { share_t *share; int id; share = (share_t *)( data - sizeof(share_t) ); id = share->id; // 공유 메모리를 어드레스 공간에서 분리한다. shmdt( share ); // 공유 메모리를 사용하는 프로세스가 없다면 삭제하도록 설정한다. shmctl( id, IPC_RMID, NULL ); } /* //------------------------------------------------------------------------------- // 설명 : // 주의 : //------------------------------------------------------------------------------- int get_usrmsg( char *buf, int size ) { printf( " type msg >> " ); fgets( buf, size, stdin ); if ( buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = 0; if ( 0 == strcmp( buf, "exit" ) ) return -1; return 0; } //------------------------------------------------------------------------------- // 설명 : help // 주의 : //------------------------------------------------------------------------------- void help( void ) { printf( " sap_shm [r|w] [key] [size]\n" \ " r|w : read or write\n" \ " key : shared mem key\n" \ " size : shared mem size\n" \ " ex) ./sap_shm r 0x1234 256\n"\ ); } // 메세지를 보내고 받기위한 구조체 typedef struct { unsigned int seq; char data[0]; } msg_t; //------------------------------------------------------------------------------ // 설명 : main // 주의 : //------------------------------------------------------------------------------ int main( int argc, char **argv ) { msg_t *pmsg; int key, size; char dir; if ( argc < 4 ) { help(); return -1; } dir = argv[1][0]; key = strtoul( argv[2], NULL, 0 ); size = strtoul( argv[3], NULL, 0 ); // 공유메모리를 생성한다. pmsg = (msg_t *)share_create( key, sizeof(msg_t) + size ); if ( NULL == pmsg ) { printf( " fail get shared mem\n" ); return -1; } // 데이타를 공유메모리에 쓴다. if ( dir == 'w' ) { pmsg->seq = 0; while( 0 == get_usrmsg( pmsg->data, size ) ) { pmsg->seq ++; } pmsg->seq ++; } // 데이타를 공유메모리에서 읽는다. else { unsigned int seq = 0; while(1) { if ( seq != pmsg->seq ) { printf( " --> %s\n", pmsg->data ); seq = pmsg->seq; if ( 0 == strcmp( pmsg->data, "exit" ) ) break; } sleep(1); } } // 공유메모리를 해제한다. share_free( pmsg ); printf( " shm test end\n" ); return 0; } */