1. 程式人生 > 實用技巧 >WIN32多程序共享日誌

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...