你的位置:首页 > 操作系统

[操作系统]6.2远程打印


因为串口打印速度慢,调试程序会影响程序的真正效果,所以引入网络打印

 

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 4typedef 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;  //发送线程IDstatic pthread_t g_tRecvTreadID;  //接收线程IDstatic 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;}