libsharememory.cpp 9.3 KB

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