因為串口列印速度慢,調試程式會影響程式的真正效果,所以引入網路列印 debug_manager.h #ifndef _DEBUG_MANAGER_H #define _DEBUG_MANAGER_H #define APP_EMERG "" /* system is unusable */ #def... ...
因為串口列印速度慢,調試程式會影響程式的真正效果,所以引入網路列印
debug_manager.h
#ifndef _DEBUG_MANAGER_H #define _DEBUG_MANAGER_H #define APP_EMERG "<0>" /* system is unusable */ #define APP_ALERT "<1>" /* action must be taken immediately */ #define APP_CRIT "<2>" /* critical conditions */ #define APP_ERR "<3>" /* error conditions */ #define APP_WARNING "<4>" /* warning conditions */ #define APP_NOTICE "<5>" /* normal but significant condition */ #define APP_INFO "<6>" /* informational */ #define APP_DEBUG "<7>" /* debug-level messages */ #define DEFAULT_DBGLEVEL 4 typedef struct DebugOpr { char *name; int isCanUse; int (*DebugInit)(void); int (*DebugExit)(void); int (*DebugPrint)(char *strData); struct DebugOpr *ptNext; }T_DebugOpr, *PT_DebugOpr; int RegisterDebugOpr(PT_DebugOpr ptDebugOpr); void ShowDebugOpr(void); PT_DebugOpr GetDebugOpr(char *pcName); int SetDbgLevel(char *strBuf); int SetDbgChanel(char *strBuf); int DebugInit(void); int DebugPrint(const char *pcFormat, ...); int InitDebugChanel(void); int NetPrintInit(void); int StdoutInit(void); #endif /* _DEBUG_MANAGER_H */
debug_manager.c
#include <config.h> #include <debug_manager.h> #include <string.h> #include <stdio.h> #include <stdarg.h> static PT_DebugOpr g_ptDebugOprHead; static int g_iDbgLevelLimit = 8; //允許所有級別列印信息 int RegisterDebugOpr(PT_DebugOpr ptDebugOpr) { PT_DebugOpr ptTmp; if (!g_ptDebugOprHead) { g_ptDebugOprHead = ptDebugOpr; ptDebugOpr->ptNext = NULL; } else { ptTmp = g_ptDebugOprHead; while (ptTmp->ptNext) { ptTmp = ptTmp->ptNext; } ptTmp->ptNext = ptDebugOpr; ptDebugOpr->ptNext = NULL; } return 0; } void ShowDebugOpr(void) { int i = 0; PT_DebugOpr ptTmp = g_ptDebugOprHead; while (ptTmp) { printf("%02d %s\n", i++, ptTmp->name); ptTmp = ptTmp->ptNext; } } PT_DebugOpr GetDebugOpr(char *pcName) { PT_DebugOpr ptTmp = g_ptDebugOprHead; while (ptTmp) { if (strcmp(ptTmp->name, pcName) == 0) { return ptTmp; } ptTmp = ptTmp->ptNext; } return NULL; } /* strBuf = "dbglevel=<0-7>" */ int SetDbgLevel(char *strBuf) { g_iDbgLevelLimit = strBuf[9] - '0'; return 0; } /* *stdout = 0 :關閉stdout列印 *stdout = 1 :打開staout列印 *netprint = 0 :關閉netprint列印 *netprint = 1 :打開netprint列印 */ int SetDbgChanel(char *strBuf) { char *pStrTmp; char strName[100]; PT_DebugOpr ptTmp; pStrTmp = strchr(strBuf,'='); //返回指向‘=’的指針 if(!pStrTmp) { return -1; } else { strncpy(strName, strBuf, pStrTmp-strBuf); strName[pStrTmp-strBuf] = '\0'; ptTmp = GetDebugOpr(strName); if(!ptTmp) return -1; if(pStrTmp[1] == '0') ptTmp->isCanUse = 0; else ptTmp->isCanUse = 1; return 0; } } int DebugPrint(const char *pcFormat, ...) { char strTmpBuf[1000]; char *pcTmp; va_list tArg; int iNum; PT_DebugOpr ptTmp = g_ptDebugOprHead; int dbglevel = DEFAULT_DBGLEVEL; va_start (tArg, pcFormat); iNum = vsprintf (strTmpBuf, pcFormat, tArg); va_end (tArg); strTmpBuf[iNum] = '\0'; pcTmp = strTmpBuf; /* 根據列印級別決定是否列印 */ if((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>')) { dbglevel = strTmpBuf[1] - '0'; if (dbglevel >= 0 && dbglevel <= 9) { pcTmp = strTmpBuf + 3; } else { dbglevel = DEFAULT_DBGLEVEL; } } if (dbglevel > g_iDbgLevelLimit) { return -1; } /* 調用鏈表中所有isCanUse為1的結構體的DebugPrint函數 */ while (ptTmp) { if(ptTmp->isCanUse) { ptTmp->DebugPrint(pcTmp); } ptTmp = ptTmp->ptNext; } return 0; } int DebugInit(void) { int iError; iError = StdoutInit(); iError |= NetPrintInit(); return iError; } int InitDebugChanel(void) { PT_DebugOpr ptTmp = g_ptDebugOprHead; while (ptTmp) { if(ptTmp->isCanUse && ptTmp->DebugInit) { ptTmp->DebugInit(); } ptTmp = ptTmp->ptNext; } return 0; }
stdout.c
#include <config.h> #include <debug_manager.h> #include <stdio.h> #include <string.h> static int StdoutDebugPrint(char *strData) { /* 直接把輸出信息用printf列印出來 */ printf("%s", strData); return strlen(strData); } static T_DebugOpr g_tStdoutDbgOpr = { .name = "stdout", .isCanUse = 1, .DebugPrint = StdoutDebugPrint, }; int StdoutInit(void) { return RegisterDebugOpr(&g_tStdoutDbgOpr); }
netprint.c
#include <config.h> #include <debug_manager.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <pthread.h> #define SERVER_PORT 5678 #define PRINT_BUF_SIZE (16 * 1024) static int g_iSocketServer; static struct sockaddr_in g_tSocketServerAddr; static struct sockaddr_in g_tSocketClientAddr; static int g_iHaveConnected = 0; static char *g_pcNetPrintBuf; static int g_iReadPos = 0; static int g_iWritePos = 0; static pthread_t g_tSendTreadID; //發送線程ID static pthread_t g_tRecvTreadID; //接收線程ID static pthread_mutex_t g_tNetDbgSendMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t g_tNetDbgSendConVar = PTHREAD_COND_INITIALIZER; static int isFull(void) { /* 寫數據追上讀數據的時候滿啦 */ return (((g_iWritePos + 1) % PRINT_BUF_SIZE) == g_iReadPos); } static int isEmpty(void) { return (g_iWritePos == g_iReadPos); } static int PutData(char cVal) { if(isFull()) return -1; else { g_pcNetPrintBuf[g_iWritePos] = cVal; g_iWritePos = (g_iWritePos + 1) % PRINT_BUF_SIZE; return 0; } } static int GetData(char *pcVal) { if(isEmpty()) return -1; else { *pcVal = g_pcNetPrintBuf[g_iReadPos]; g_iReadPos = (g_iReadPos + 1) % PRINT_BUF_SIZE; return 0; } } static void *NetDbgSendTreadFunction(void *pVoid) { char strTmpBuf[512]; char cVal; int i; int iAddrLen; int iSendLen; while(1) { /* 平時休眠 */ pthread_mutex_lock(&g_tNetDbgSendMutex); pthread_cond_wait(&g_tNetDbgSendConVar, &g_tNetDbgSendMutex); pthread_mutex_unlock(&g_tNetDbgSendMutex); /* 條件等待函數 */ while((g_iHaveConnected && !isEmpty())) { i = 0; /* 把環形緩衝區的數據最多取512位元組 */ while((i < 512) && (0 == GetData(&cVal))) { strTmpBuf[i] = cVal; i++; } /* 程式能夠向下繼續證明被喚醒啦 */ /* 用sendto函數發送列印信息到客戶端 */ iAddrLen = sizeof(struct sockaddr); iSendLen = sendto(g_iSocketServer, strTmpBuf, i, 0, (const struct sockaddr *)&g_tSocketClientAddr, iAddrLen); } } return NULL; } static void *NetDbgRecvTreadFunction(void *pVoid) { socklen_t iAddrLen; int iRecvLen; char ucRecvBuf[1000]; struct sockaddr_in tSocketClientAddr; while(1) { iAddrLen = sizeof(struct sockaddr); DBG_PRINTF("in NetDbgRecvTreadFunction\n"); iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen); if(iRecvLen > 0) { ucRecvBuf[iRecvLen] = '\0'; DBG_PRINTF("netprint.c get msg: %s\n", ucRecvBuf); /* 解析數據 : * setclient : 設置接收列印信息的客戶端 * dbglevel=0,1,2... : 修改列印級別 *stdout = 0 :關閉stdout列印 * stdout=1 : 打開stdout列印 *netprint = 0 :關閉netprint列印 *netprint = 1 :打開netprint列印 */ if(strcmp(ucRecvBuf, "setclient") == 0) { /* 成功連接且設置為 */ g_tSocketClientAddr = tSocketClientAddr; g_iHaveConnected = 1; } else if (strncmp(ucRecvBuf, "dbglevel=", 9) == 0) { SetDbgLevel(ucRecvBuf); } else { SetDbgChanel(ucRecvBuf); } } } return NULL; } static int NetDbgInit(void) { /* 初始化socket */ int iRet; g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == g_iSocketServer) { printf("socket error!\n"); return -1; } g_tSocketServerAddr.sin_family = AF_INET; g_tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */ g_tSocketServerAddr.sin_addr.s_addr = INADDR_ANY; memset(g_tSocketServerAddr.sin_zero, 0, 8); iRet = bind(g_iSocketServer, (const struct sockaddr *)&g_tSocketServerAddr, sizeof(struct sockaddr)); if (-1 == iRet) { printf("bind error!\n"); return -1; } g_pcNetPrintBuf = malloc(PRINT_BUF_SIZE); if(NULL == g_pcNetPrintBuf) { close(g_iSocketServer); return -1; } /* 創建netprint發送線程: 它用來發送列印信息給客戶端 */ pthread_create(&g_tSendTreadID, NULL, NetDbgSendTreadFunction, NULL); /* 創建netprint接收線否: 用來接收控制信息,比如修改列印級別,打開/關閉列印 */ pthread_create(&g_tRecvTreadID, NULL, NetDbgRecvTreadFunction, NULL); return 0; } static int NetDbgExit(void) { /* 關閉socket,... */ close(g_iSocketServer); free(g_pcNetPrintBuf); } static int NetDbgPrint(char *strData) { /* 把數據放入環形緩衝區, */ int i; for(i = 0; i < strlen(strData); i++) { if(0 != PutData(strData[i])) break; } /* 如果已經有客戶端連接了, 就把數據通過網路發送給客戶端 */ /* 喚醒netprint的發送線程 */ pthread_mutex_lock(&g_tNetDbgSendMutex); pthread_cond_signal(&g_tNetDbgSendConVar); pthread_mutex_unlock(&g_tNetDbgSendMutex); return i; } static T_DebugOpr g_tNetDbgOpr = { .name = "netprint", .isCanUse = 1, .DebugInit = NetDbgInit, .DebugExit = NetDbgExit, .DebugPrint = NetDbgPrint, }; int NetPrintInit(void) { return RegisterDebugOpr(&g_tNetDbgOpr); }
netprint_client.c
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <signal.h> /*socket * connet * send/recv */ #define SERVER_PORT 5678 /* * ./netprint_client <server_ip> dbglevel=<0-9> * ./netprint_client <server_ip> stdout=0|1 * ./netprint_client <server_ip> netprint=0|1 * ./netprint_client <server_ip> show // setclient,²¢ÇÒ½ÓÊÕ´òÓ¡ÐÅÏ¢ */ int main(int argc, char **argv) { int iSocketClient; struct sockaddr_in tSocketServerAddr; int iRet; unsigned char ucRecvBuf[1000]; int iSendLen; int iAddrLen; int iRecvLen; if (argc != 3) { printf("Usage:\n"); printf("%s <server_ip> dbglevel=<0-9>\n", argv[0]); printf("%s <server_ip> stdout=0|1\n", argv[0]); printf("%s <server_ip> netprint=0|1\n", argv[0]); printf("%s <server_ip> show\n", argv[0]); return -1; } iSocketClient = socket(AF_INET, SOCK_DGRAM, 0); tSocketServerAddr.sin_family = AF_INET; tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net ,short */ if(0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr)) /* ±¾»úÉϵÄËùÓÐIP */ { printf("invalid server_ip\n"); return -1; } memset(tSocketServerAddr.sin_zero, 0, 8); /* ÉèÖÃÎÞÓõĿռäΪ0 */ if (strcmp(argv[2], "show") == 0) { /* ·¢ËÍÊý¾Ý */ iAddrLen = sizeof(struct sockaddr); iSendLen = sendto(iSocketClient, "setclient", 9, 0, (const struct sockaddr *)&tSocketServerAddr, iAddrLen); while (1) { /* Ñ»·: ´ÓÍøÂç¶ÁÊý¾Ý, ´òÓ¡³öÀ´ */ iAddrLen = sizeof(struct sockaddr); iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketServerAddr, &iAddrLen); if (iRecvLen > 0) { ucRecvBuf[iRecvLen] = '\0'; printf("%s\n", ucRecvBuf); } } } else { /* ·¢ËÍÊý¾Ý */ iAddrLen = sizeof(struct sockaddr); iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0, (const struct sockaddr *)&tSocketServerAddr, iAddrLen); } return 0; }