// libsharememory.cpp : 定义 DLL 应用程序的导出函数。 // #ifdef _WIN32 #include "stdafx.h" #include #else #include #include #include #include #include #include #include #include #endif #include "libsharememory.h" class libsharememory_impl { protected: unsigned int m_dwBytes; bool m_bLocked; void* m_pData; #ifdef _WIN32 HANDLE m_hFileMap; HANDLE m_hMutex; #else int m_shid; sem_t* m_semt; char m_strsemname[MAX_PATH]; char m_strshmname[MAX_PATH]; #endif // _WIN32 public: libsharememory_impl() { #ifdef _WIN32 m_hMutex = NULL; m_hFileMap = NULL; #else m_shid = -1; m_semt = SEM_FAILED; memset(m_strsemname, 0, MAX_PATH); memset(m_strshmname, 0, MAX_PATH); #endif // _WIN32 m_dwBytes=0; m_pData=NULL; m_bLocked = false; } ~libsharememory_impl() { CloseShareMem(); } //创建共享内存区 bool CreateShareMem(const char* szName, unsigned int dwBytes) { bool bRet = false; #ifdef _WIN32 char szBuf[MAX_PATH] = {0}; const char* szFile; if (szName != NULL && dwBytes > 0) { CloseShareMem(); szFile = tmpnam(szBuf); if (szFile != NULL) { m_hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, dwBytes + sizeof(unsigned int) + sizeof(int), szName); if (m_hFileMap != NULL) { m_dwBytes = dwBytes; m_pData = MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (m_pData != NULL) { *((LPDWORD)m_pData) = dwBytes; _snprintf(szBuf, MAX_PATH, "Mutex<%s>", szName); m_hMutex = CreateMutex(NULL, false, szBuf); if (m_hMutex != NULL) { if (GetLastError() != ERROR_ALREADY_EXISTS) { bRet = true; } } } } if (!bRet) { CloseShareMem(); } } } #else if (szName != NULL && dwBytes > 0) { char szBuf[MAX_PATH] = { 0 }; const char* szFile = tmpnam(szBuf); if (szFile != NULL) { snprintf(m_strshmname, MAX_PATH, "%s", szName); snprintf(m_strsemname, MAX_PATH, "/mutex.%s", szName); m_shid = shm_open(szName, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (m_shid >= 0) { //Debug("%s:%d shm_open O_CREAT|O_RDWR|O_EXCL success and share memory %s and size is %d", __FUNCTION__, __LINE__, szName, dwBytes); } else { //Debug("%s:%d shm_open O_CREAT|O_RDWR|O_EXCL %s failed for %s, and errno is %d", __FUNCTION__, __LINE__, m_strshmname, strerror(errno), errno); if (EEXIST == errno) { m_shid = shm_open(szName, O_RDWR, 0); } } if (m_shid >= 0) { if (NULL == m_pData) { ftruncate(m_shid, dwBytes); m_pData = mmap(NULL, dwBytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_shid, 0); if (MAP_FAILED != m_pData) { *((unsigned int*)m_pData) = dwBytes; m_dwBytes = dwBytes; sem_t* semt = sem_open(m_strsemname, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 1); if (NULL == semt) { if (EEXIST == errno) { semt = sem_open(m_strsemname, 0); sem_init(semt, 32, 1); } } if (NULL != semt) { m_semt = semt; int ivalue = -1; sem_getvalue(m_semt, &ivalue); bRet = true; } } } } } } #endif // _WIN32 return bRet; } //打开已有的共享内存区 bool OpenShareMem(const char* szName) { bool bRet = false; #ifdef _WIN32 char szBuf[MAX_PATH]; if (szName != NULL) { CloseShareMem(); m_hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, szName); if (m_hFileMap != NULL) { sprintf_s(szBuf, "Mutex<%s>", szName); m_hMutex = OpenMutex(MUTEX_ALL_ACCESS, false, szBuf); if (m_hMutex != NULL) { m_pData = MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (LockShareMem()) { m_dwBytes = *((LPDWORD)m_pData); //m_nEntityNum = *((int*)((LPDWORD)m_pData+1)); //*((int*)((LPDWORD)m_pData+1)) = ++m_nEntityNum; UnlockShareMem(); if (m_dwBytes > 0) { bRet = true; } } } } if (!bRet) { CloseShareMem(); } } #else if (szName != NULL) { int shid = shm_open(szName, O_RDWR, 0); if (-1 != shid) { m_shid = shid; sem_t* semt = sem_open(m_strsemname, 0); if (SEM_FAILED != semt){ m_semt = semt; int ivalue = -1; sem_getvalue(semt, &ivalue); m_pData = mmap(NULL, m_dwBytes, PROT_READ | PROT_WRITE, MAP_SHARED, shid, 0); if (MAP_FAILED != m_pData) { if (LockShareMem()){ m_dwBytes = *((unsigned int*)m_pData); UnlockShareMem(); if (m_dwBytes > 0){ bRet = true; } } } } } if (!bRet){ CloseShareMem(); } } #endif // RVC_OS_WIN return bRet; } //释放共享内存区 void CloseShareMem() { if (m_bLocked){ UnlockShareMem(); } #ifdef _WIN32 if (m_pData != NULL){ UnmapViewOfFile(m_pData); m_pData = NULL; } if (m_hFileMap != NULL){ CloseHandle(m_hFileMap); m_hFileMap = NULL; } if (m_hMutex != NULL){ CloseHandle(m_hMutex); m_hMutex = NULL; } #else if (SEM_FAILED != m_semt){ sem_unlink(m_strsemname); m_semt = SEM_FAILED; } if (m_pData != NULL){ munmap(m_pData, m_dwBytes); } if (m_shid >= 0) { shm_unlink(m_strshmname); m_shid = -1; } #endif //_MSC_VER m_dwBytes = 0; } //获取共享内存区大小 unsigned int GetShareMemBytes() { return m_dwBytes; } //是否有可用的内存区 bool IsShareMemValid() { #ifdef _WIN32 return (m_hFileMap != NULL && m_hMutex != NULL); #else return (m_shid != -1 && m_semt != NULL); #endif // _WIN32 } //锁定访问内存区 void* LockShareMem(unsigned int dwWaitTimeout=INFINITE) { void* pData=NULL; if (IsShareMemValid() && m_pData != NULL && !m_bLocked) { #ifdef _WIN32 if (WaitForSingleObject(m_hMutex, dwWaitTimeout) != WAIT_TIMEOUT){ m_bLocked = true; } if (m_bLocked){ pData = (void*)((LPDWORD)m_pData + 1); } #else struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long unsec = ts.tv_nsec + (1000*1000*dwWaitTimeout); ts.tv_sec += (unsec / 1000000000); ts.tv_nsec = (unsec % 1000000000); int ivalue = -1; sem_getvalue(m_semt, &ivalue); if (0 == sem_timedwait(m_semt,&ts)) { sem_getvalue(m_semt, &ivalue); m_bLocked = true; } #endif // _WIN32 if (m_bLocked){ pData = (void*)((unsigned int*)m_pData + 1); } } return pData; } //内存区是否互斥锁定 bool IsShareMemLocked() { return m_bLocked; } //解锁内存区 void UnlockShareMem() { if (m_bLocked) { #ifdef _WIN32 ReleaseMutex(m_hMutex); #else sem_post(m_semt); #endif // _WIN32 m_bLocked = false; } } }; // 这是已导出类的构造函数。 // 有关类定义的信息,请参阅 libsharememory.h Clibsharememory::Clibsharememory() { m_pImpl = new libsharememory_impl; return; } Clibsharememory::~Clibsharememory() { delete m_pImpl; } void Clibsharememory::Unlock() { m_pImpl->UnlockShareMem(); return; } bool Clibsharememory::IsLocked() { bool bRst = m_pImpl->IsShareMemLocked(); return bRst; } void* Clibsharememory::Lock(unsigned int dwWaitTimeout) { void* lpVoid = m_pImpl->LockShareMem(dwWaitTimeout); return lpVoid; } bool Clibsharememory::IsValid() { bool bRst = m_pImpl->IsShareMemValid(); return bRst; } unsigned int Clibsharememory::GetBytes() { unsigned int TotalBytes = m_pImpl->GetShareMemBytes(); return TotalBytes; } void Clibsharememory::Close() { m_pImpl->CloseShareMem(); return; } bool Clibsharememory::Open(const char* szName) { return m_pImpl->OpenShareMem(szName); } bool Clibsharememory::Create(const char* szName, unsigned int dwBytes) { return m_pImpl->CreateShareMem(szName,dwBytes); }