libsharememory.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. // libsharememory.cpp : 定义 DLL 应用程序的导出函数。
  2. //
  3. #include "stdafx.h"
  4. #include "libsharememory.h"
  5. #include <stdio.h>
  6. //#include "SpBase.h"
  7. //#define TESTSHAREMEM 0
  8. void Debug(const char* fmt, ...)
  9. {
  10. // char strfmt[512] = { 0 };
  11. // va_list args;
  12. // va_start(args, fmt);
  13. // vsprintf(strfmt, fmt, args);
  14. //#ifdef TESTSHAREMEM
  15. // printf("%s\n", strfmt);
  16. //#else
  17. // Dbg("%s", strfmt);
  18. //#endif
  19. // va_end(args);
  20. // fflush(stdout);
  21. }
  22. class libsharememory_impl
  23. {
  24. protected:
  25. unsigned int m_dwBytes;
  26. bool m_bLocked;
  27. void* m_pData;
  28. //HANDLE m_hFile;
  29. #ifdef RVC_OS_WIN
  30. HANDLE m_hFileMap;
  31. HANDLE m_hMutex;
  32. #else
  33. //void* m_hFileMap;
  34. int m_shid;
  35. sem_t* m_semt;
  36. char m_strsemname[MAX_PATH];
  37. char m_strshmname[MAX_PATH];
  38. #endif // RVC_OS_WIN
  39. public:
  40. libsharememory_impl()
  41. {
  42. m_pData=NULL;
  43. m_bLocked = false;
  44. #ifdef RVC_OS_WIN
  45. m_hFileMap = NULL;
  46. m_hMutex = NULL;
  47. #else
  48. m_shid = -1;
  49. m_semt = NULL;
  50. memset(m_strsemname, 0, MAX_PATH);
  51. memset(m_strshmname, 0, MAX_PATH);
  52. #endif // RVC_OS_WIN
  53. m_dwBytes=0;
  54. }
  55. ~libsharememory_impl()
  56. {
  57. CloseShareMem();
  58. }
  59. #ifdef RVC_OS_WIN
  60. #else
  61. bool CreateShareMemLinux(const char* szName, unsigned int dwBytes)
  62. {
  63. bool bRet = false;
  64. if (szName != NULL && dwBytes > 0) {
  65. char szBuf[MAX_PATH] = {0};
  66. const char* szFile = tmpnam(szBuf);
  67. if (szFile != NULL) {
  68. snprintf(m_strshmname, MAX_PATH, "%s", szName);
  69. snprintf(m_strsemname, MAX_PATH, "/mutex.%s", szName);
  70. m_shid = shm_open(szName, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
  71. if (m_shid >= 0) {
  72. //Debug("%s:%d shm_open O_CREAT|O_RDWR|O_EXCL success and share memory %s and size is %d", __FUNCTION__, __LINE__, szName, dwBytes);
  73. }
  74. else {
  75. //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);
  76. if (EEXIST == errno) {
  77. m_shid = shm_open(szName, O_RDWR, 0);
  78. }
  79. }
  80. if (m_shid >= 0){
  81. if (NULL == m_pData){
  82. ftruncate(m_shid, dwBytes);
  83. m_pData = mmap(NULL, dwBytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_shid, 0);
  84. if (MAP_FAILED != m_pData) {
  85. *((LPDWORD)m_pData) = dwBytes;
  86. m_dwBytes = dwBytes;
  87. sem_t* semt = sem_open(m_strsemname, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 1);
  88. if (NULL == semt) {
  89. if (EEXIST == errno) {
  90. semt = sem_open(m_strsemname, 0);
  91. sem_init(semt,32, 1);
  92. }
  93. }
  94. if (NULL != semt) {
  95. m_semt = semt;
  96. int ivalue = -1;
  97. sem_getvalue(m_semt, &ivalue);
  98. bRet = true;
  99. }
  100. }
  101. }
  102. }
  103. }
  104. }
  105. return bRet;
  106. }
  107. #endif
  108. //创建共享内存区
  109. bool CreateShareMem(const char* szName, unsigned int dwBytes)
  110. {
  111. bool T =false;
  112. #ifdef RVC_OS_WIN
  113. char szBuf[MAX_PATH];
  114. const char* szFile;
  115. if (szName != NULL && dwBytes > 0)
  116. {
  117. CloseShareMem();
  118. szFile = tmpnam(szBuf);
  119. if (szFile != NULL)
  120. {
  121. m_hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, dwBytes + sizeof(unsigned int) + sizeof(int), szName);
  122. if (m_hFileMap != NULL)
  123. {
  124. m_dwBytes = dwBytes;
  125. m_pData = MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  126. if (m_pData != NULL)
  127. {
  128. *((LPDWORD)m_pData) = dwBytes;
  129. //*((int*)((LPDWORD)m_pData+1))= ++m_nEntityNum;
  130. sprintf_s(szBuf, "Mutex<%s>", szName);
  131. m_hMutex = CreateMutex(NULL, false, szBuf);
  132. if (m_hMutex != NULL)
  133. {
  134. if (GetLastError() != ERROR_ALREADY_EXISTS)
  135. {
  136. T = true;
  137. }
  138. }
  139. }
  140. }
  141. if (!T)
  142. {
  143. CloseShareMem();
  144. }
  145. }
  146. }
  147. #else
  148. T = CreateShareMemLinux(szName, dwBytes);
  149. #endif // RVC_OS_WIN
  150. return T;
  151. }
  152. //打开已有的共享内存区
  153. bool OpenShareMem(const char* szName)
  154. {
  155. bool T=false;
  156. #ifdef RVC_OS_WIN
  157. char szBuf[MAX_PATH];
  158. if (szName != NULL)
  159. {
  160. CloseShareMem();
  161. m_hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, szName);
  162. if (m_hFileMap != NULL)
  163. {
  164. sprintf_s(szBuf, "Mutex<%s>", szName);
  165. m_hMutex = OpenMutex(MUTEX_ALL_ACCESS, false, szBuf);
  166. if (m_hMutex != NULL)
  167. {
  168. m_pData = MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  169. if (LockShareMem())
  170. {
  171. m_dwBytes = *((LPDWORD)m_pData);
  172. //m_nEntityNum = *((int*)((LPDWORD)m_pData+1));
  173. //*((int*)((LPDWORD)m_pData+1)) = ++m_nEntityNum;
  174. UnlockShareMem();
  175. if (m_dwBytes > 0)
  176. {
  177. T = true;
  178. }
  179. }
  180. }
  181. }
  182. if (!T)
  183. {
  184. CloseShareMem();
  185. }
  186. }
  187. #else
  188. if (szName != NULL) {
  189. int shid = shm_open(szName, O_RDWR, 0);
  190. if (-1 != shid) {
  191. m_shid = shid;
  192. sem_t* semt = sem_open(m_strsemname, 0);
  193. if (SEM_FAILED != semt){
  194. m_semt = semt;
  195. int ivalue = -1;
  196. sem_getvalue(semt, &ivalue);
  197. m_pData = mmap(NULL, m_dwBytes, PROT_READ | PROT_WRITE, MAP_SHARED, shid, 0);
  198. if (MAP_FAILED != m_pData) {
  199. if (LockShareMem()){
  200. m_dwBytes = *((LPDWORD)m_pData);
  201. UnlockShareMem();
  202. if (m_dwBytes > 0)
  203. {
  204. T = true;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. if (!T){
  211. CloseShareMem();
  212. }
  213. }
  214. #endif // RVC_OS_WIN
  215. return T;
  216. }
  217. //释放共享内存区
  218. void CloseShareMem()
  219. {
  220. #ifdef RVC_OS_WIN
  221. if (m_bLocked)
  222. {
  223. UnlockShareMem();
  224. }
  225. if (m_pData != NULL)
  226. {
  227. UnmapViewOfFile(m_pData);
  228. m_pData = NULL;
  229. }
  230. if (m_hFileMap != NULL)
  231. {
  232. CloseHandle(m_hFileMap);
  233. m_hFileMap = NULL;
  234. }
  235. if (m_hMutex != NULL)
  236. {
  237. CloseHandle(m_hMutex);
  238. m_hMutex = NULL;
  239. }
  240. m_dwBytes = 0;
  241. #else
  242. if (m_bLocked){
  243. UnlockShareMem();
  244. }
  245. if (NULL != m_semt){
  246. sem_unlink(m_strsemname);
  247. }
  248. if (m_pData != NULL){
  249. munmap(m_pData, m_dwBytes);
  250. }
  251. shm_unlink(m_strshmname);
  252. m_dwBytes = 0;
  253. #endif // _WIN32
  254. }
  255. //获取共享内存区大小
  256. unsigned int GetShareMemBytes()
  257. {
  258. return m_dwBytes;
  259. }
  260. //是否有可用的内存区
  261. bool IsShareMemValid()
  262. {
  263. #ifdef RVC_OS_WIN
  264. return (m_hFileMap != NULL && m_hMutex != NULL);
  265. #else
  266. return (m_shid != -1 && m_semt != NULL);
  267. #endif // RVC_OS_WIN
  268. }
  269. //锁定访问内存区
  270. void* LockShareMem(unsigned int dwWaitTimeout=INFINITE)
  271. {
  272. void* pData=NULL;
  273. #ifdef RVC_OS_WIN
  274. if (IsShareMemValid() && m_pData != NULL && !m_bLocked)
  275. {
  276. if (WaitForSingleObject(m_hMutex, dwWaitTimeout) != WAIT_TIMEOUT)
  277. {
  278. m_bLocked = true;
  279. }
  280. if (m_bLocked)
  281. {
  282. pData = (void*)((LPDWORD)m_pData + 1);
  283. }
  284. }
  285. #else
  286. //Debug("IsShareMemValid flag is %d, m_pData = 0x%08x, m_bLocked flag is %s.", IsShareMemValid(), m_pData, m_bLocked ? "true" : "false");
  287. if (IsShareMemValid() && m_pData != NULL && !m_bLocked)
  288. {
  289. struct timespec ts;
  290. clock_gettime(CLOCK_REALTIME, &ts);
  291. long unsec = ts.tv_nsec + (1000*1000*dwWaitTimeout);
  292. ts.tv_sec += (unsec / 1000000000);
  293. ts.tv_nsec = (unsec % 1000000000);
  294. int ivalue = -1;
  295. sem_getvalue(m_semt, &ivalue);
  296. if (0 == sem_timedwait(m_semt,&ts))
  297. {
  298. sem_getvalue(m_semt, &ivalue);
  299. m_bLocked = true;
  300. }
  301. if (m_bLocked)
  302. {
  303. pData = (void*)((LPDWORD)m_pData + 1);
  304. }
  305. }
  306. #endif // _WIN32
  307. return pData;
  308. }
  309. //内存区是否互斥锁定
  310. bool IsShareMemLocked()
  311. {
  312. return m_bLocked;
  313. }
  314. //解锁内存区
  315. void UnlockShareMem()
  316. {
  317. #ifdef RVC_OS_WIN
  318. if (m_bLocked)
  319. {
  320. ReleaseMutex(m_hMutex);
  321. m_bLocked = false;
  322. }
  323. #else
  324. if (m_bLocked)
  325. {
  326. sem_post(m_semt);
  327. m_bLocked = false;
  328. }
  329. #endif // _WIN32
  330. }
  331. };
  332. // 这是已导出类的构造函数。
  333. // 有关类定义的信息,请参阅 libsharememory.h
  334. Clibsharememory::Clibsharememory()
  335. {
  336. m_pImpl = new libsharememory_impl;
  337. return;
  338. }
  339. Clibsharememory::~Clibsharememory()
  340. {
  341. delete m_pImpl;
  342. }
  343. void Clibsharememory::Unlock()
  344. {
  345. m_pImpl->UnlockShareMem();
  346. return;
  347. }
  348. bool Clibsharememory::IsLocked()
  349. {
  350. bool bRst = m_pImpl->IsShareMemLocked();
  351. return bRst;
  352. }
  353. void* Clibsharememory::Lock(unsigned int dwWaitTimeout)
  354. {
  355. void* lpVoid = m_pImpl->LockShareMem(dwWaitTimeout);
  356. return lpVoid;
  357. }
  358. bool Clibsharememory::IsValid()
  359. {
  360. bool bRst = m_pImpl->IsShareMemValid();
  361. return bRst;
  362. }
  363. unsigned int Clibsharememory::GetBytes()
  364. {
  365. unsigned int TotalBytes = m_pImpl->GetShareMemBytes();
  366. return TotalBytes;
  367. }
  368. void Clibsharememory::Close()
  369. {
  370. m_pImpl->CloseShareMem();
  371. return;
  372. }
  373. bool Clibsharememory::Open(const char* szName)
  374. {
  375. bool bRst = m_pImpl->OpenShareMem(szName);
  376. return bRst;
  377. }
  378. bool Clibsharememory::Create(const char* szName, unsigned int dwBytes)
  379. {
  380. bool bRst = m_pImpl->CreateShareMem(szName,dwBytes);
  381. return bRst;
  382. }