WIN32多进程共享日志
为了解决多个应用进程的日志融合输出的问题,设计了如下的方案。
1 /************************************************************************/ 2 /* SharedLogging.h 多进程共享日志模块 */ 3 /************************************************************************/ 4 5 #ifndef __SHARED_LOGGING_H_20200811__ 6 #define __SHARED_LOGGING_H_20200811__ 7 8 #pragma once 9 10 #ifdef SHAREDLOGGING_EXPORTS 11 #define SHAREDLOGGING_API __declspec(dllexport) 12 #else 13 #define SHAREDLOGGING_API __declspec(dllimport) 14 #endif 15 16 #include <Windows.h> 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif /* __cplusplus */ 21 22 23 typedef void (*incomingLogging)(void *user_data, wchar_t const *logging_texts, unsigned logging_length); 24 /**< 版本号 */ 25 SHAREDLOGGING_API unsigned SharedLoggingVersion(void); 26 /**< 建立连接 */ 27 SHAREDLOGGING_API HANDLE SharedLoggingConnect(const wchar_t* moudle_name); 28 /**< 断开连接 */ 29 SHAREDLOGGING_API int SharedLoggingDisconnect(HANDLE handle); 30 /**< 写入日志 */ 31 SHAREDLOGGING_API int SharedLoggingWrite(HANDLE handle, const wchar_t *logging_text, unsigned text_length); 32 /**< 订阅日志 */ 33 SHAREDLOGGING_API int SharedLoggingSubscribe(HANDLE handle, incomingLogging cb, void *user_data); 34 /**< 取消订阅 */ 35 SHAREDLOGGING_API int SharedLoggingUnsubscribe(HANDLE handle); 36 /**< 读出最后一条日志 */ 37 SHAREDLOGGING_API int SharedLoggingRead(HANDLE handle, wchar_t *logging, unsigned length); 38 39 #ifdef __cplusplus 40 } 41 #endif /* __cplusplus */ 42 43 #endif //__SHARED_LOGGING_H_20200811__
主要源代码,如下:
1 /************************************************************************/ 2 /* SharedLogging.cpp 多进程共享日志模块 */ 3 /************************************************************************/ 4 #include "stdafx.h" 5 #include "SharedLogging.h" 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <process.h> 9 10 #define MAX(a,b) ((a>b)?a:b) 11 #define MIN(a,b) ((a<b)?a:b) 12 13 #ifdef WIN32 14 15 #ifdef _DEBUG 16 /**< 重定义调试打印输出 */ 17 #define debug(format,...) \ 18 do \ 19 { \ 20 wprintf(L"[D] FUNC: %S, LINE: %d: ",strrchr(__FILE__,'\\')+1,__LINE__); \ 21 wprintf(TEXT(format), ##__VA_ARGS__); \ 22 printf("\r\n"); \ 23 }while(0) 24 #endif 25 /**< 重定义错误打印输出 */ 26 #define error(format,...) \ 27 do \ 28 { \ 29 wprintf(L"[E] FUNC: %S, LINE: %d: ",strrchr(__FILE__,'\\')+1,__LINE__); \ 30 wprintf(TEXT(format), ##__VA_ARGS__); \ 31 printf("\r\n"); \ 32 }while(0) 33 #endif 34 35 #define ALLOC_ONE(type) ((type *)malloc(sizeof(type))) 36 #define EXIT_ASSERT(val) do{if (!val) {error("failed in this"); getchar(); exit(1);}}while(0) 37 #define SET_ZERO(ptr, type) (memset(ptr, 0, sizeof(type))) 38 39 40 #define VERSION_MAIN 1 41 #define VERSION_SUB 0 42 #define VERSION_NUM ((unsigned)(VERSION_MAIN << 8)|(VERSION_SUB)) 43 44 #define SHARED_LOGGING_NAME L"SharedLoggingMapFile" 45 #define SHARED_LOGGING_MUTEX_NAME L"SharedLoggingMutex" 46 #define SHARED_LOGGING_SEMAPHORE_NAME L"SharedLoggingSemaphore" 47 48 #define MAX_SEMAPHORE_NUM 4 49 #define MAX_BASE_NAME_SIZE 16 50 #define MAX_MAIL_TEXT_SIZE 128 51 #define SHARED_LOGGING_GLOBAL_SIZE 80 52 #define SHARED_LOGGING_ITEM_NUM 256 53 #define SHARED_LOGGING_ITEM_SIZE 160 // 0x50 54 #define SHARED_LOGGING_MEMORY_SIZE ((SHARED_LOGGING_ITEM_NUM * SHARED_LOGGING_ITEM_SIZE) + SHARED_LOGGING_GLOBAL_SIZE) 55 56 57 58 struct shared_logging_base 59 { 60 wchar_t name[MAX_BASE_NAME_SIZE]; /**< 把进程的名字放进这里(用户提供) */ 61 incomingLogging cb; /**< 后台线程的处理例程(用户提供) */ 62 void *user_data; /**< 处理例程的用户私有数据(用户提供) */ 63 unsigned offsetRead; /**< 当前读入的偏移值 */ 64 HANDLE hMap; /**< 共享内存的句柄 */ 65 HANDLE hMutex; /**< 共享内存的互斥锁 */ 66 HANDLE hSemaphore; /**< 信号量,通知其他进程的订阅者 */ 67 LPVOID pBuffer; /**< 共享内存的首地址 */ 68 unsigned shutdown; /**< 关闭后台线程的标志 */ 69 HANDLE hThread; /**< 后台线程的句柄 */ 70 HANDLE hEvent; /**< 未使用 */ 71 CRITICAL_SECTION csLock; /**< 多线程的临界区 */ 72 }; 73 typedef struct shared_logging_base sl_base_st; 74 75 struct shared_logging_global 76 { 77 unsigned version; /**< 版本号,格式:低16bit,前8bit是主版本号,后8bit是次版本号 */ 78 unsigned capacity_items_num; /**< 预设置的条目容量,超过的时候会覆盖最前面的 */ 79 unsigned total_items_num; /**< 当前的条目的数量(从创建为止到目前的累计总数) */ 80 unsigned write_item_offset; /**< 当前的写入偏移值,超过最大容量的时候,恢复到0 */ 81 }; 82 typedef struct shared_logging_global sl_global_st; 83 84 85 86 static unsigned __stdcall fnQueueHandler(void *arg); 87 static int CompareCurrentOffset(sl_base_st *base, unsigned offset); 88 89 static sl_base_st *CreateUserDescription(const wchar_t *name) 90 { 91 sl_base_st *base = ALLOC_ONE(sl_base_st); /**< 创建用户的私有数据 */ 92 EXIT_ASSERT(base); 93 SET_ZERO(base, sl_base_st); 94 wcsncpy(base->name, name, MAX_BASE_NAME_SIZE-1); 95 base->name[MAX_BASE_NAME_SIZE-1] = L'\0'; /**< 手动添加结尾空字符 */ 96 debug("base name is %s", name); 97 return base; 98 } 99 100 /**< 打开共享内存 */ 101 static int OpenMapFile(sl_base_st *base) 102 { 103 unsigned isNew = 0; /**< 刚刚新建的 */ 104 sl_global_st *global = NULL; /**< 共享内存的全局变量结构的地址 */ 105 LPVOID pBuffer = NULL; /**< 共享内存指针 */ 106 107 HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, SHARED_LOGGING_NAME); 108 if (!hMap) /**< 打开失败,创建之 */ 109 { 110 debug("OpenFileMapping failed"); 111 hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, /**< 物理文件句柄 */ 112 NULL, /**< 默认安全级别 */ 113 PAGE_READWRITE, /**< 可读可写 */ 114 0, /**< 高位文件大小 */ 115 SHARED_LOGGING_MEMORY_SIZE, /**< 地位文件大小 */ 116 SHARED_LOGGING_NAME); /**< 共享内存名称 */ 117 EXIT_ASSERT(hMap); 118 isNew = 1; 119 } 120 if (hMap) 121 { 122 /**< 映射对象的一个视图,得到指向共享内存的指针,设置里面的数据 */ 123 pBuffer = ::MapViewOfFile(hMap, /**< 共享内存的句柄 */ 124 FILE_MAP_ALL_ACCESS, /**< 可读写许可 */ 125 0, /**< 表示文件映射起始偏移的高32位 */ 126 0, /**< 表示文件映射起始偏移的低32位.(64KB对齐不是必须的) */ 127 0); /**< 指定映射文件的字节数 */ 128 EXIT_ASSERT(pBuffer); 129 if (isNew) 130 memset(pBuffer, 0, SHARED_LOGGING_MEMORY_SIZE); 131 } 132 if (pBuffer) 133 { 134 global = (sl_global_st *)pBuffer; 135 if ((isNew) || (global->version <= VERSION_NUM)) /**< 假如后者的版本号更新,则重置所有数据 */ 136 { 137 debug("Reset global info"); 138 global->version = VERSION_NUM; 139 global->capacity_items_num = SHARED_LOGGING_ITEM_NUM; 140 global->total_items_num = 0; 141 global->write_item_offset = 0; 142 } 143 base->pBuffer = pBuffer; 144 base->hMap = hMap; 145 return 0; 146 } 147 return -1; 148 149 } 150 151 /**< 打开共享内存的读写互斥锁 */ 152 static int OpenWriteMutex(sl_base_st *base) 153 { 154 HANDLE hMutex; 155 hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE,SHARED_LOGGING_MUTEX_NAME); 156 if (NULL == hMutex) 157 { 158 debug("OpenMutex failed"); 159 hMutex = CreateMutex(NULL, FALSE, SHARED_LOGGING_MUTEX_NAME);/**< 打开失败,创建之 */ 160 EXIT_ASSERT(hMutex); 161 } 162 base->hMutex = hMutex; 163 return (hMutex?0:-1); 164 } 165 /**< 打开共享内存的信号量(发送端) */ 166 static int OpenWriteEvent(sl_base_st *base) 167 { 168 HANDLE hSemaphore; 169 /**< 打开信号量 */ 170 hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS , FALSE,SHARED_LOGGING_SEMAPHORE_NAME); 171 if (NULL == hSemaphore) /**< 打开失败,创建之 */ 172 { 173 debug("OpenSemaphore failed"); 174 hSemaphore = CreateSemaphore(NULL, /**< 安全属性,如果为NULL则是默认安全属性 */ 175 0, /**< 信号量的初始值,要>=0且<=第三个参数 */ 176 MAX_SEMAPHORE_NUM, /**< 信号量的最大值 */ 177 SHARED_LOGGING_SEMAPHORE_NAME); /**< 信号量的名称 */ 178 EXIT_ASSERT(hSemaphore); 179 } 180 base->hSemaphore = hSemaphore; 181 return (hSemaphore?0:-1); 182 } 183 184 /**< 发送任意数据到订阅者的邮槽 */ 185 static int PostWriteEvent(sl_base_st *base) 186 { 187 debug("ReleaseSemaphore"); 188 return (ReleaseSemaphore(base->hSemaphore, MAX_SEMAPHORE_NUM, NULL)==TRUE)?0:-1; 189 } 190 191 static int CatchWriteEvent(sl_base_st *base) 192 { 193 while(1) 194 { 195 debug("WaitForSingleObject Prev\n"); 196 if(WaitForSingleObject(base->hSemaphore,INFINITE) == WAIT_OBJECT_0) 197 { 198 if (0 == CompareCurrentOffset(base, base->offsetRead)) 199 { 200 debug("Continue"); 201 continue; 202 } 203 else 204 { 205 debug("Break"); 206 break; 207 } 208 } 209 } 210 } 211 212 static int LockWriteMutex(sl_base_st *base) /**< 共享互斥锁 */ 213 { 214 DWORD ret = WaitForSingleObject(base->hMutex, INFINITE); 215 if (ret == WAIT_OBJECT_0) 216 { 217 debug("Normal mutex"); 218 return 0; 219 } 220 else if (ret == WAIT_ABANDONED) 221 { 222 debug("Abandoned mutex"); 223 return -1; 224 } 225 else{ 226 debug("Unkown mutex"); 227 return -2; 228 } 229 } 230 static int UnlockWriteMutex(sl_base_st *base) /**< 共享互斥锁 */ 231 { 232 debug("ReleaseMutex"); 233 return (ReleaseMutex(base->hMutex)==TRUE)?0:-1; 234 } 235 236 static int ReleaseHandle(sl_base_st *base) 237 { 238 if (base) /**< 解除文件映射,关闭内存映射文件对象句柄 */ 239 { 240 if (base->hSemaphore) 241 { 242 debug("Release hSemaphore"); 243 CloseHandle(base->hSemaphore); 244 } 245 246 if (base->hThread) 247 { 248 debug("Release hThread"); 249 CloseHandle(base->hThread); 250 } 251 if (base->pBuffer) 252 { 253 debug("Release pBuffer"); 254 UnmapViewOfFile(base->pBuffer); 255 } 256 if (base->hMutex) 257 { 258 debug("Release hMutex"); 259 CloseHandle(base->hMutex); 260 } 261 if (base->hMap) 262 { 263 debug("Release hMap"); 264 CloseHandle(base->hMap); 265 } 266 free(base); 267 debug("ReleaseHandle success"); 268 return 0; 269 } 270 debug("ReleaseHandle failed"); 271 return -1; 272 } 273 274 static size_t WriteMapFile(sl_base_st *base, void *buffer, size_t length) 275 { 276 sl_global_st *global = (sl_global_st *)base->pBuffer; /**< 共享内存指针 */ 277 size_t wlen = MIN(length, SHARED_LOGGING_ITEM_SIZE); 278 279 unsigned offset = (global->write_item_offset * SHARED_LOGGING_ITEM_SIZE) + SHARED_LOGGING_GLOBAL_SIZE; 280 memcpy(((unsigned char *)base->pBuffer) + offset, buffer, wlen); 281 if ((global->write_item_offset + 1) >= global->capacity_items_num) 282 global->write_item_offset = 0; 283 else 284 global->write_item_offset += 1; 285 286 global->total_items_num += 1; 287 debug("Write is %d, Total is %d", global->write_item_offset, global->total_items_num); 288 return wlen; 289 } 290 291 static size_t ReadMapFileForNextItem(sl_base_st *base, void *buffer, size_t length) 292 { 293 sl_global_st *global = (sl_global_st *)base->pBuffer; /**< 共享内存指针 */ 294 size_t wlen = MIN(length, SHARED_LOGGING_ITEM_SIZE); /**< 最小的长度 */ 295 unsigned offset = ((base->offsetRead) * SHARED_LOGGING_ITEM_SIZE) + SHARED_LOGGING_GLOBAL_SIZE; 296 297 memcpy(buffer, ((unsigned char *)base->pBuffer) + offset, wlen); 298 if ((base->offsetRead + 1) >= global->capacity_items_num) 299 base->offsetRead = 0; 300 else 301 base->offsetRead += 1; 302 debug("Read is %d", base->offsetRead); 303 return wlen; 304 305 } 306 307 static size_t ReadMapFileForLastItem(sl_base_st *base, void *buffer, size_t length) 308 { 309 sl_global_st *global = (sl_global_st *)base->pBuffer; /**< 共享内存指针 */ 310 size_t wlen = MIN(length, SHARED_LOGGING_ITEM_SIZE); /**< 最小的长度 */ 311 312 unsigned offset = 0; 313 if (global->write_item_offset > 0) /**< 非首写位置的话 */ 314 { 315 offset = ((global->write_item_offset - 1) * SHARED_LOGGING_ITEM_SIZE) + SHARED_LOGGING_GLOBAL_SIZE; 316 } 317 else if (global->total_items_num > 0) /**< 若首写位置的话,则要再加上非零记录的判断 */ 318 { 319 offset = ((global->total_items_num - 1) * SHARED_LOGGING_ITEM_SIZE) + SHARED_LOGGING_GLOBAL_SIZE; 320 } 321 else 322 return 0; 323 debug("Write is %d", global->write_item_offset); 324 memcpy(buffer, ((unsigned char *)base->pBuffer) + offset, wlen); 325 return wlen; 326 } 327 328 static int inline CompareCurrentOffset(sl_base_st *base, unsigned offset) 329 { 330 sl_global_st *global = (sl_global_st *)base->pBuffer; /**< 共享内存指针 */ 331 332 if (global->write_item_offset == offset){ 333 debug("offset is the same"); 334 return 0; 335 } 336 else 337 { 338 debug("offset is not the same"); 339 return -1; 340 } 341 } 342 343 /**< 版本号 */ 344 SHAREDLOGGING_API unsigned SharedLoggingVersion(void) 345 { 346 return VERSION_NUM; 347 } 348 349 /**< 建立连接 */ 350 SHAREDLOGGING_API HANDLE SharedLoggingConnect(const wchar_t* moudle_name) 351 { 352 sl_base_st *base = CreateUserDescription(moudle_name); 353 354 if ((!OpenWriteMutex(base)) 355 && (!OpenMapFile(base)) 356 && (!OpenWriteEvent(base))) 357 { 358 debug("SharedLoggingConnect success"); 359 return (HANDLE)base; 360 } 361 else 362 { 363 free(base); 364 debug("free base"); 365 return INVALID_HANDLE_VALUE; 366 } 367 } 368 369 /**< 断开连接 */ 370 SHAREDLOGGING_API int SharedLoggingDisconnect(HANDLE handle) 371 { 372 debug("SharedLoggingDisconnect"); 373 return ReleaseHandle((sl_base_st *)handle); 374 } 375 376 /**< 写入日志 */ 377 SHAREDLOGGING_API int SharedLoggingWrite(HANDLE handle, const wchar_t *logging, unsigned length) 378 { 379 sl_base_st *base = (sl_base_st *)handle; 380 debug(" ==> %s", logging); 381 LockWriteMutex(base); 382 size_t rlen = WriteMapFile(base, (LPVOID)logging, sizeof(wchar_t) * length); 383 UnlockWriteMutex(base); 384 PostWriteEvent(base); 385 return rlen; 386 } 387 388 /**< 读出最后一条日志 */ 389 SHAREDLOGGING_API int SharedLoggingRead(HANDLE handle, wchar_t *logging, unsigned length) 390 { 391 sl_base_st *base = (sl_base_st *)handle; 392 LockWriteMutex(base); 393 size_t rlen = ReadMapFileForLastItem(base, (LPVOID)logging, sizeof(wchar_t) * length); 394 UnlockWriteMutex(base); 395 debug(" <== %s", logging); 396 return rlen; 397 } 398 399 /**< 订阅 */ 400 SHAREDLOGGING_API int SharedLoggingSubscribe(HANDLE handle, incomingLogging cb, void *user_data) 401 { 402 sl_base_st *base = (sl_base_st *)handle; 403 404 /**< 初始化队列的临界区 */ 405 InitializeCriticalSection(&base->csLock); 406 407 /**< 初始化事件信号 */ 408 HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 409 if (NULL == hEvent) 410 { 411 error("CreateEvent failed"); 412 DeleteCriticalSection(&base->csLock); 413 return -1; 414 } 415 416 /**< 创建事件队列的处理线程 */ 417 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, fnQueueHandler, handle, 0, NULL); 418 if (!hThread) 419 { 420 error("_beginthreadex failed"); 421 CloseHandle(hEvent); 422 DeleteCriticalSection(&base->csLock); 423 return -2; 424 } 425 426 base->hThread = hThread; 427 base->hEvent = hEvent; 428 base->cb = cb; 429 base->user_data = user_data; 430 431 debug("SharedLoggingSubscribe success"); 432 return 0; 433 } 434 435 436 /**< 取消订阅 */ 437 SHAREDLOGGING_API int SharedLoggingUnsubscribe(HANDLE handle) 438 { 439 sl_base_st *base = (sl_base_st *)handle; 440 441 EnterCriticalSection(&base->csLock);/**< 进入临界区 */ 442 base->shutdown = 1; 443 LeaveCriticalSection(&base->csLock);/**< 退出临界区 */ 444 445 SetEvent(base->hEvent); 446 /**< 等待子线程结束 */ 447 if (base->hThread){ 448 debug("Release hThread"); 449 WaitForSingleObject(base->hThread, INFINITE); 450 /**< 一定要记得关闭线程句柄 */ 451 CloseHandle(base->hThread); 452 base->hThread = NULL; 453 } 454 if (base->hEvent){ 455 debug("Release hEvent"); 456 CloseHandle(base->hEvent); 457 base->hEvent = NULL; 458 } 459 460 DeleteCriticalSection(&base->csLock); /**< 删除临界区 */ 461 debug("SharedLoggingUnsubscribe success"); 462 return -1; 463 } 464 465 static unsigned __stdcall fnQueueHandler(void *arg) 466 { 467 sl_base_st *base = (sl_base_st *)arg; 468 CRITICAL_SECTION *pLock = &base->csLock; 469 HANDLE hEvent[2] = {base->hEvent, base->hSemaphore}; 470 HANDLE hThread = base->hThread; 471 char buffer[SHARED_LOGGING_ITEM_SIZE]; 472 wchar_t *logging = (wchar_t *)buffer; 473 474 debug("fnQueueHandler ready"); 475 476 while (true) 477 { 478 while ((base->shutdown == 0) 479 &&(CompareCurrentOffset(base, base->offsetRead) == 0)) 480 { 481 LeaveCriticalSection(pLock);/**< 退出临界区 */ 482 DWORD ret = WaitForMultipleObjects(2,hEvent, FALSE, INFINITE); 483 debug("WaitForMultipleObjects is %d", ret); 484 EnterCriticalSection(pLock);/**< 进入临界区 */ 485 } 486 if (base->shutdown == 1) 487 { 488 debug("fnQueueHandler shutdown"); 489 LeaveCriticalSection(pLock);/**< 退出临界区 */ 490 break; 491 } 492 memset(buffer, 0, SHARED_LOGGING_ITEM_SIZE); 493 LockWriteMutex(base); 494 ReadMapFileForNextItem(base, buffer, SHARED_LOGGING_ITEM_SIZE); 495 UnlockWriteMutex(base); 496 LeaveCriticalSection(pLock);//**< 退出临界区 */ 497 498 if (base->cb) 499 { 500 debug("enter user callback"); 501 (base->cb)(base->user_data, logging, wcslen(logging)); 502 debug("exit user callback"); 503 } 504 505 EnterCriticalSection(pLock);/**< 进入临界区 */ 506 } 507 508 debug("fnQueueHandler exit"); 509 510 return 0; 511 }
测试代码-写入端,如下:
1 // Tester.cpp : 定义控制台应用程序的入口点。 2 // 3 /************************************************************************/ 4 /* Tester.cpp */ 5 /************************************************************************/ 6 #include "stdafx.h" 7 #include "SharedLogging.h" 8 9 #define SAY_HELLO L"Hello world!" 10 #define SAY_GOOD L"Good world!" 11 #define SAY_BYE L"Bye world!" 12 13 int _tmain(int argc, _TCHAR* argv[]) 14 { 15 wchar_t buffer[256]; 16 int rlen = 0; 17 18 printf("Version : 0x%x\n", SharedLoggingVersion()); 19 20 HANDLE handle = SharedLoggingConnect(L"Tester"); 21 22 printf("handle %p\n", handle); 23 24 printf("Enter any key to start...\n"); 25 26 getchar(); 27 28 SharedLoggingWrite(handle, SAY_HELLO, wcslen(SAY_HELLO)); 29 30 getchar(); 31 32 SharedLoggingWrite(handle, SAY_GOOD, wcslen(SAY_GOOD)); 33 34 getchar(); 35 36 SharedLoggingWrite(handle, SAY_BYE, wcslen(SAY_BYE)); 37 38 getchar(); 39 40 SharedLoggingDisconnect(handle); 41 42 printf("Enter any key to exit...\n"); 43 44 getchar(); 45 46 return 0; 47 }
测试代码--接收端,如下:
/************************************************************************/ /* Tester2.cpp */ /************************************************************************/ #include "stdafx.h" #include "SharedLogging.h" void cbLogging(void *user_data, wchar_t const*logging_texts, unsigned logging_length) { wprintf(L"text : %s \n", logging_texts); } int _tmain(int argc, _TCHAR* argv[]) { HANDLE handle = SharedLoggingConnect(L"Tester1"); printf("handle %p\n", handle); printf("Enter any key to subscribe...\n"); getchar(); SharedLoggingSubscribe(handle, cbLogging, handle); printf("Enter any key to unsubscribe...\n"); getchar(); SharedLoggingUnsubscribe(handle); printf("Enter any key to disconnect...\n"); getchar(); SharedLoggingDisconnect(handle); printf("Enter any key to exit...\n"); getchar(); return 0; }
测试效果,如下:
发送端: Version : 0x100 [D] FUNC: sharedlogging.cpp, LINE: 98: base name is Tester [D] FUNC: sharedlogging.cpp, LINE: 160: OpenMutex failed [D] FUNC: sharedlogging.cpp, LINE: 112: OpenFileMapping failed [D] FUNC: sharedlogging.cpp, LINE: 139: Reset global info [D] FUNC: sharedlogging.cpp, LINE: 175: OpenSemaphore failed [D] FUNC: sharedlogging.cpp, LINE: 360: SharedLoggingConnect success handle 00A42FD8 Enter any key to start... 接收端: [D] FUNC: sharedlogging.cpp, LINE: 98: base name is Tester1 [D] FUNC: sharedlogging.cpp, LINE: 139: Reset global info [D] FUNC: sharedlogging.cpp, LINE: 360: SharedLoggingConnect success handle 00A34EE0 Enter any key to subscribe... 发送端: [D] FUNC: sharedlogging.cpp, LINE: 382: ==> Hello world! [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 289: Write is 1, Total is 1 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 189: ReleaseSemaphore 接收端: [D] FUNC: sharedlogging.cpp, LINE: 433: SharedLoggingSubscribe success Enter any key to unsubscribe... [D] FUNC: sharedlogging.cpp, LINE: 476: fnQueueHandler ready [D] FUNC: sharedlogging.cpp, LINE: 340: offset is not the same [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 304: Read is 1 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 502: enter user callback text : Hello world! [D] FUNC: sharedlogging.cpp, LINE: 504: exit user callback [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same 发送端: [D] FUNC: sharedlogging.cpp, LINE: 382: ==> Good world! [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 289: Write is 2, Total is 2 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 189: ReleaseSemaphore 接收端: [D] FUNC: sharedlogging.cpp, LINE: 304: Read is 2 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 502: enter user callback text : Good world! [D] FUNC: sharedlogging.cpp, LINE: 504: exit user callback [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same 发送端: [D] FUNC: sharedlogging.cpp, LINE: 382: ==> Bye world! [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 289: Write is 3, Total is 3 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 189: ReleaseSemaphore 接收端: [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 304: Read is 3 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 502: enter user callback text : Bye world! [D] FUNC: sharedlogging.cpp, LINE: 504: exit user callback [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same 发送端: [D] FUNC: sharedlogging.cpp, LINE: 374: SharedLoggingDisconnect [D] FUNC: sharedlogging.cpp, LINE: 244: Release hSemaphore [D] FUNC: sharedlogging.cpp, LINE: 255: Release pBuffer [D] FUNC: sharedlogging.cpp, LINE: 260: Release hMutex [D] FUNC: sharedlogging.cpp, LINE: 265: Release hMap [D] FUNC: sharedlogging.cpp, LINE: 269: ReleaseHandle success Enter any key to exit... 接收端: [D] FUNC: sharedlogging.cpp, LINE: 219: Normal mutex [D] FUNC: sharedlogging.cpp, LINE: 304: Read is 3 [D] FUNC: sharedlogging.cpp, LINE: 234: ReleaseMutex [D] FUNC: sharedlogging.cpp, LINE: 502: enter user callback text : Bye world! [D] FUNC: sharedlogging.cpp, LINE: 504: exit user callback [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 1 [D] FUNC: sharedlogging.cpp, LINE: 335: offset is the same 接收端--退出: [D] FUNC: sharedlogging.cpp, LINE: 450: Release hThread [D] FUNC: sharedlogging.cpp, LINE: 485: WaitForMultipleObjects is 0 [D] FUNC: sharedlogging.cpp, LINE: 490: fnQueueHandler shutdown [D] FUNC: sharedlogging.cpp, LINE: 510: fnQueueHandler exit [D] FUNC: sharedlogging.cpp, LINE: 457: Release hEvent [D] FUNC: sharedlogging.cpp, LINE: 463: SharedLoggingUnsubscribe success Enter any key to disconnect... [D] FUNC: sharedlogging.cpp, LINE: 374: SharedLoggingDisconnect [D] FUNC: sharedlogging.cpp, LINE: 244: Release hSemaphore [D] FUNC: sharedlogging.cpp, LINE: 255: Release pBuffer [D] FUNC: sharedlogging.cpp, LINE: 260: Release hMutex [D] FUNC: sharedlogging.cpp, LINE: 265: Release hMap [D] FUNC: sharedlogging.cpp, LINE: 269: ReleaseHandle success Enter any key to exit...
关键要点总结:
1、接收端的个数,目前是固定值4(>=1),假如那个实际接收端小于这个值,会造成多次查询,浪费性能。优化方案:将接收端个数写入全局变量中。
2、发送端,可以支持多线程安全访问。
3、每一条日志的长度是固定的,会浪费空间。优化方案:将offset值修改成内存指针的方式。