/*************************************************************************** rc_mond shared memory template header ----------------------------------------- begin : 2015/06/15 copyright : (C) 2005 Solbox Inc. author : Storage Dev Team email : huibong@solbox.com version : 3.5 CopyRight(C) 2005 Solbox Inc. All Rights reserved. Redistribution and use in source and binary forms, with or with out modification, are not permitted in outside of Solbox Inc. ***************************************************************************/ // 본 코드는 시스템 공유메모리 생성, 접근, 해제, 삭제 처리를 수행하기 위한 코드로서 // template 코드 방식으로 구성 #ifndef __SHM_CONTROL_H__ #define __SHM_CONTROL_H__ #include #include #include /*----------- MODE Flag --------------- SHM_R 0400 read by user SHM_W 0200 write by user SHM_R >> 3 0040 read by group SHM_W >> 3 0020 write by group SHM_R >> 6 0004 read by others SHM_W >> 6 0002 write by others -------------------------------------*/ //////////////////////////////////////////////////////////////////////////////////////////////// /// @brief ShmControl 공유메모리 관련 Template Class template class CShmControl { public: /// @brief 생성자 CShmControl(); /// @brief 소멸자 ~CShmControl(); /// @brief 공유메모리 생성, 접근 또는 기존 공유메모리 접근. /// @param iShmKey 공유메모리 접근을 위한 키 /// @param iSize 접근하고자 하는 공유메모리의 크기 /// @param iSize 공유메모리 생성및 접근시 권한 /// @return return true or false bool Create( key_t iShmKey, size_t iSize, int iModeFlag = SHM_R | SHM_W ); /// @brief 기존 공유메모리 접근. /// @param iShmKey 공유메모리 접근을 위한 키 /// @param iSize 접근하고자 하는 공유메모리의 크기 /// @param iSize 공유메모리 접근시 권한 /// @return return true or false bool Attach( key_t iShmKey, size_t iSize, int iModeFlag = SHM_R | SHM_W ); /// @brief 기존 접근한 공유메모리와의 연결을 해제 /// @return return true or false bool Detach( void ); /// @brief 기존 접근한 공유메모리와의 연결을 해제 및 삭제 /// @return return true or false bool Remove( void ); /// @brief 공유메모리에 대한 포인터를 반환 /// @return 생성 및 접근한 공유메모리에 대한 포인터 또는 오류 발생시 NULL T * GetShmPtr(void) const { return m_pShm; } /// @brief 접근한 공유메모리의 ID 값을 반환 /// @return 생성 및 접근한 공유메모리 ID Value에 대한 참조. int GetShmId(void) const { return m_iShmId; } private: ///< m_pShm 공유메모리에 대한 포인터 T * m_pShm; ///< m_pShmId 접근한 공유메모리의 ID Value int m_iShmId; }; //////////////////////////////////////////////////////////////////////////////////////////////// // 기본 멤버변수 초기화. template < typename T > inline CShmControl::CShmControl() : m_pShm(NULL) , m_iShmId(-1) { } template < typename T > inline CShmControl::~CShmControl() { // 생성된 공유메모리를 종료시 다른 프로세스들이 사용한다면.. 맘대로 삭제해서는 안되며... // 이럴 경우 detach 처리만 해야 한다. // Detach(); // 이와 반대로.. 다른 프로세스에서 더이상 해당 공유메모리를 사용하지 않을 경우.. remove 처리한다. Remove(); } // 해당 공유메모리를 생성한다. 만약 기존에 생성된 것이 있다면 그놈을 사용하도록 한다. template < typename T > inline bool CShmControl::Create( key_t iShmKey, size_t iSize, int iModeFlag ) { // 우선 공유 메모리를 생성해 봅니다. m_iShmId = shmget( iShmKey, iSize, IPC_CREAT | IPC_EXCL | iModeFlag ); // 생성에 실패한 경우. if( m_iShmId == -1) { // 이미 기존에 생성된 놈이 있는지 확인해 봅시다. return Attach( iShmKey, iSize, iModeFlag); } // 생성에 성공한 경우. else { // 생성된 공유 메모리의 포인터를 받아옵니다. m_pShm = (T *)shmat( m_iShmId, 0, 0 ); // 받아온 공유 메모리 포인터 값이 정확하면 if( reinterpret_cast(m_pShm) != -1) { // 원래 시스템에서 생성시 자동으로 초기화됨 => 그렇지만 새로이 생성을 하였으므로 확인 사살 초기화 ^^ memset( m_pShm, 0x00, iSize); return true; } // 받아온 공유 메모리 포인터를 가져오는데 실패한 경우 // => 만든놈이 삭제해 버립시다. else { Remove(); return false; } } } // 기존에 생성된 것 공유 메모리에 접근하기 위해서 사용한다.. // 키값과 크기값을 정확히 알고 있어야 ( 혹시 다른데서 사용하는 놈으로 붙을까봐 ) 접근할 수 있도록 한다. template < typename T > inline bool CShmControl::Attach( key_t iShmKey, size_t iSize, int iModeFlag ) { // 기존 연결은 해제 시켜 버린다. => 그냥 놓은 상태에서 다시 접속할 경우 메모리 사용량이 올라감. Detach(); m_iShmId = shmget( iShmKey, iSize, iModeFlag); if( m_iShmId == -1 ) return false; else { // 우선 기존에 있는 것과 크기가 동일한지 검사한다. struct shmid_ds shmInfo; memset(&shmInfo, 0x00, sizeof(struct shmid_ds)); shmctl( m_iShmId, IPC_STAT, &shmInfo); // shm_segsz 정의 관련 참고사항 // - FreeBSD 6.X : int type으로 정의되어.. 컴파일시 waring 발생 // - FreeBSD 10.X : size_t type // - CentOS 6.4 : size_t type if( shmInfo.shm_segsz != iSize) return false; else { m_pShm = (T *)shmat( m_iShmId, 0, 0 ); // reinterpret_cast 을 사용한 것은 운영체제마다 포인터 형이 다를수가 있다고 참고한 라이브러리에 나와있어서 함. if( reinterpret_cast(m_pShm) == -1) return false; else return true; } } } // 접근한 공유메모리로 부터 분리시킨다. ( 접근시 설정된 멤버 변수 이용) template < typename T > inline bool CShmControl::Detach() { if( m_pShm > 0 ) { if( shmdt( m_pShm) == 0) { m_iShmId = -1; m_pShm = NULL; return true; } else return false; } else return true; } // 공유메모리를 삭제한다. 이 작업을 하기 위해서는 먼저 공유 메모리를 생성 또는 접근을 해야하며 // 이때 설정된 멤버 변수를 가지고 삭제 작업을 수행한다. // 공유 메모리는 여러 Process 들이 사용가능하기 때문에 삭제시 신중을 기할 것. template < typename T > inline bool CShmControl::Remove() { if( m_iShmId > -1) { if( shmctl( m_iShmId, IPC_RMID, NULL) == -1) return false; else { m_iShmId = -1; m_pShm = NULL; return true; } } return true; } #endif /* __SHM_CONTROL_H__ */