嵌入式软件

人生在世如身处荆棘之中,心不动,人不妄动,不动则不伤;如心动则人妄动,伤其身痛其骨,于是体会到世间诸般痛苦。

用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
embeddedsoft的公告
<a href="http://www2.clustrmaps.com/counter/maps.php?url=http://blog.csdn.net/embeddedsoft" id="clustrMapsLink"><img src="http://www2.clustrmaps.com/counter/index2.php?url=http://blog.csdn.net/embeddedsoft" style="border:1px solid;" alt="Locations of visitors to this page" title="Locations of visitors to this page" id="clustrMapsImg" onError="this.onError=null; this.src='http://clustrmaps.com/images/clustrmaps-back-soon.jpg'; document.getElementById('clustrMapsLink').href='http://clustrmaps.com'" /> </a> <img src="http://services.nexodyne.com/email/icon/ZnlnDst%2BZ1V1BaI6/QKII3LI%3D/WWFob28%3D/1/image.png"> I got a master degree in Zhejiang University of Science and Technology and have been dealing with embedded software development for years since graduation.I'd like to share my thoughts with you readily. <embed src="http://www.clocklink.com/clocks/0001-blue.swf?TimeZone=CCT&Place=&" width="200" height="200" wmode="transparent" type="application/x-shockwave-flash">
文章分类
IT了望台
Amine&vxworks
chinaUnix
comp.os.vxworks
embedded.com
gjcamann vxworks
Jack Ganssle
中国最权威VxWorks论坛
嵌入式世界网
电子工程专辑
网络U盘
通用便携
同道中人
absurd
dishening
embeddedsoft
glock18
ifq
lzcx
peter lee
tangl_99
孟岩
杨争
陈皓
存档

原创  数据流量监测工具[视频会议][源玛共享] 收藏

  最近视频会议的一个模块总是有点不对劲,从网络接收的数据到缓冲并转发到网络的过程中发现数据流不正常,为了便于调试并清楚到底有多少数据收到并以多少速率转发到网络,决定写一个可以监测数据流量的工具。感觉这个工具在查看多路多点位置的数据流非常好用。推荐一下,希望大家多提意见。不明白的,请多提问题哦。

NOTE:这段代码在cygwin下调试过,结果看最后。本人的真正开发环境是vxworks下,所以在下面的代码中也附带了vxworks的相应部分。

1. 单通道版本

#include <stdio.h>
#include <string.h>

/* 工具功能 : 测试流媒体数据流经模块内部
  * 各个点的流量统计信息,用于软件问题的诊断调试
  * 工具功能 :在需要监测的位置添加一段监测 代码(见DEMO)
  * 然后调用PacketPrint() 并传入监测时间,过一段时间就可以看到结果。 
  * 工具DEMO    : 
  * {
  *  static short nCallerID = INVALID_VALUE;
  *
  *  PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  * }

*/

#define CYGWIN_ENVIRONMENT   /*定义测试环境*/

#define INVALID_VALUE   -1
#define MAX_CALLERS    30   /*流量统计监测点的最大数目*/
#define MAX_FUNC_NAME_LEN  100  /*监测点调用函数的函数名最大长度*/
#define MAX_MONITOR_SECONDS  99  /*流量统计时间,单位为秒*/
#define MAX_PACKET_NUM   60*(MAX_MONITOR_SECONDS+1)/*最大测试包数*/ 

#define TRUE      1 
#define FALSE     0

typedef struct _TagCallerInfo

 char   pFuncName[MAX_FUNC_NAME_LEN]; /*调用函数的函数名,caller名称*/
 char   nFuncLen;/*调用函数的函数名实际长度*/  
 short  nLine;/*调用函数的调用点位置*/  

}TCallerInfo;

typedef struct _TagPacketInfo

 int    nPackets;  /*监测点流经总包数*/ 
 int    nPacketRate; /*监测点流量*/ 
 int    nPrevPackets; /*该点上一次监测的累计包数*/  
 long   nPrevTicks;  /*该点上一次监测的累计时间*/
 int    nInterval;  /*前后两次监测的时间跨度*/
 
}TPacketInfo;


static TCallerInfo  g_tCaller[MAX_CALLERS];
static TPacketInfo g_tPacket[MAX_CALLERS];
static int    g_nCallers   = 0;

void PacketStat(char* pFuncName,short nLine,short* pCallerID);
void PacketPrint(int nInterval/*second*/);

void hello(void);
void world(void);
void delay(void);

#ifdef CYGWIN_ENVIRONMENT   
int main(int argc, char *argv[])
{
 int i;

 hello();/*监测1,caller 为hello*/
 world();/*监测2,caller 为world*/
}
#else/*vxworks*/
void usrAppInit (void)
{
#ifdef USER_APPL_INIT
 USER_APPL_INIT;
#endif

     /* add application specific code here */
  hello();/*监测1,caller 为hello*/
 world();/*监测2,caller 为world*/
}

#endif

void hello(void)
{
 int i,j;

 for (i = 0 ; i < MAX_PACKET_NUM; i++)
 {
#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/   
  delay();
#else/*vxworks*/
  taskDelay(3);/*模拟20 包每秒的速率*/     
#endif

  /*----- 包率监测点具体位置---*/
  {
   static short nCallerID = INVALID_VALUE;

   PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  }
  /*--------------------------------------*/  
 }
}

void world(void)
{
 int i,j;

 for (i = 0 ; i < MAX_PACKET_NUM; i++)
 {
#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/   
  delay();
#else/*vxworks*/
  taskDelay(3);/*模拟20 包每秒的速率*/     
#endif

  /*----- 包率监测点具体位置---*/
  {
   static short nCallerID = INVALID_VALUE;

   PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  }
  /*--------------------------------------*/  
 }
}

#ifdef CYGWIN_ENVIRONMENT   
void delay(void)
{
 int i=10000;

 while(i-->0)/*延时10000 cycles,任意定义,可以是其它值*/
  ;
}
#endif

void PacketStat(char* pFuncName,short nLine,short* pCallerID)
{
 int    nCaller    = 0;
 long   nCurrTicks   = 0; 
 static int   bInitialized   = FALSE;
 TCallerInfo*  ptCaller   = NULL;
 TPacketInfo* ptPacket  = NULL;
 
 if (NULL == pFuncName || NULL == pCallerID)
 {
  printf("invalid function name and pos pointer!");
  return;
 }

 if (!bInitialized)
 { /*第一次要初始化*/
  memset(&g_tCaller[0],0,sizeof(TCallerInfo)*MAX_CALLERS);
  memset(&g_tPacket[0],0,sizeof(TPacketInfo)*MAX_CALLERS);
  bInitialized = TRUE;
 }
  
 if (INVALID_VALUE == *pCallerID)
 { /*如果是某监测点第一次调用该函数*/
  nCaller    = g_nCallers++; 
  ptCaller    = &g_tCaller[nCaller];
  
  ptCaller->nFuncLen = strlen(pFuncName);

  if (ptCaller->nFuncLen>MAX_FUNC_NAME_LEN)
  {
   printf("too long function name!\n");  
   return;
  }

  ptCaller->nFuncLen  = sprintf(ptCaller->pFuncName,"%s",pFuncName);

  ptCaller->nLine  = nLine;
  *pCallerID    = nCaller;/*返回当前监测点的ID,以备后用*/

#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/
  PacketPrint(MAX_MONITOR_SECONDS);
#endif
 }
 else
 {
  nCaller = *pCallerID;
 }

 ptCaller  = &g_tCaller[nCaller];
 ptPacket  = &g_tPacket[nCaller];

 /*等待用户设置检测时间*/
 if (ptPacket->nInterval <1)
 { 
  return;
 }

 if (nCaller >= 0 && nCaller<MAX_CALLERS)
 {
  ptPacket->nPackets++;

#ifdef CYGWIN_ENVIRONMENT/*设置包率为1 个tick 一个包的情况,测试代码的正确性*/ 
  nCurrTicks = ptPacket->nPackets;
#else
  nCurrTicks = tickGet();
#endif
  if (0 == ptPacket->nPrevTicks)
  {
   ptPacket->nPrevPackets  = ptPacket->nPackets;
   ptPacket->nPrevTicks   = nCurrTicks;
  }
  else
  {
   if (nCurrTicks-ptPacket->nPrevTicks >= ptPacket->nInterval*60)
   {
    ptPacket->nPacketRate = 60*(ptPacket->nPackets - ptPacket->nPrevPackets)
     /(nCurrTicks - ptPacket->nPrevTicks);

    printf("%s %5d:packets %d,rate %d p/s\n",ptCaller->pFuncName,
     ptCaller->nLine,ptPacket->nPackets,ptPacket->nPacketRate);

    ptPacket->nPrevTicks  = 0;
    ptPacket->nInterval  = 0;
   }
  }
 }
}

void PacketPrint(int nInterval/*second*/)
{
 int nCaller;

 for (nCaller = 0; nCaller < g_nCallers; nCaller++)
 {    
  g_tPacket[nCaller].nInterval = nInterval;
 }
}
 

 2. 多通道改进版本

 #ifdef PACKET_RATE_MONITOR
#include <string.h>
#define MAX_CALLERS    30   /*流量统计监测点的最大数目*/
#define MAX_CHANNELS    64   /*每个监测点支持通道的最大数目*/

#define MAX_FUNC_NAME_LEN  30  /*监测点调用函数的函数名最大长度*/
#define MAX_HINT_INFO_LEN   80  /*监测点调用函数的函数名最大长度*/
#define MAX_MONITOR_SECONDS  99  /*流量统计时间,单位为秒*/
#define MAX_PACKET_NUM   60*(MAX_MONITOR_SECONDS+1)/*最大测试包数*/ 

typedef struct _TagCallerInfo

 NW_CHAR pchFuncName[MAX_FUNC_NAME_LEN]; /*调用函数的函数名,caller名称*/
 NW_CHAR  nFuncLen;/*调用函数的函数名实际长度*/  
 NW_SHORT nLine;/*调用函数的调用点位置*/  

}TCallerInfo;

typedef struct _TagPacketInfo

 NW_INT32  nPackets[MAX_CHANNELS];  /*监测点流经总包数*/ 
 NW_INT32  nPacketRate[MAX_CHANNELS]; /*监测点流量*/ 
 NW_INT32 nPrevPackets[MAX_CHANNELS];/*该点上一次监测的累计包数*/  
 NW_INT32 nPrevTicks[MAX_CHANNELS]; /*该点上一次监测的累计时间*/
 NW_INT32  nInterval[MAX_CHANNELS];     /*前后两次监测的时间跨度*/
 
}TPacketInfo;


static TCallerInfo  g_tCaller[MAX_CALLERS];
static TPacketInfo g_tPacket[MAX_CALLERS];
static NW_INT32 g_nCallers = 0;

void PacketRatePrint(int nInterval/*second*/);

void PacketRateStat(NW_CHAR* pchFuncName,NW_SHORT nLine,NW_SHORT* pCallerID,NW_SHORT nChannelID)
{
 NW_INT32   nCaller    = 0;
 NW_INT32  nCurrTicks   = 0; 
 static NW_BOOL  bInitialized   = FALSE;
 TCallerInfo*   ptCaller   = NULL;
 TPacketInfo*  ptPacket  = NULL;
 
 if (NULL == pchFuncName || NULL == pCallerID)
 {
  printf("invalid function name and pos pointer!");
  return;
 }

 if (nChannelID < 0 || nChannelID >= MAX_CHANNELS)
 {
  printf("invalid channel id %d!",nChannelID);
  return;
 } 

 if (!bInitialized)
 { /*第一次要初始化*/
  memset(&g_tCaller[0],0,sizeof(TCallerInfo)*MAX_CALLERS);
  memset(&g_tPacket[0],0,sizeof(TPacketInfo)*MAX_CALLERS);
  bInitialized = TRUE;
 }
  
 if (INVALID_VALUE == *pCallerID)
 { /*如果是某监测点第一次调用该函数*/
  nCaller     = g_nCallers++; 
  ptCaller     = &g_tCaller[nCaller];
  
  ptCaller->nFuncLen = strlen(pchFuncName);

  if (ptCaller->nFuncLen>MAX_FUNC_NAME_LEN)
  {
   printf("too long function name!\n");  
   return;
  }

  ptCaller->nFuncLen  = sprintf(ptCaller->pchFuncName,"%s",pchFuncName);
  ptCaller->nLine  = nLine;
  *pCallerID    = nCaller;/*返回当前监测点的ID,以备后用*/
 }
 else
 {
  nCaller = *pCallerID;
 }

 ptCaller  = &g_tCaller[nCaller];
 ptPacket  = &g_tPacket[nCaller];

 /*等待用户设置检测时间*/
 if (ptPacket->nInterval[nChannelID] <1)
 { 
  return;
 }

 if (nCaller >= 0 && nCaller<MAX_CALLERS)
 {
  ptPacket->nPackets[nChannelID]++;

  nCurrTicks = tickGet();

  if (0 == ptPacket->nPrevTicks[nChannelID])
  {
   ptPacket->nPrevPackets[nChannelID]  = ptPacket->nPackets[nChannelID];
   ptPacket->nPrevTicks[nChannelID]   = nCurrTicks;
  }
  else
  {
   if (nCurrTicks-ptPacket->nPrevTicks[nChannelID] >= ptPacket->nInterval[nChannelID]*60)
   {
    ptPacket->nPacketRate[nChannelID] = 60*(ptPacket->nPackets[nChannelID] - ptPacket->nPrevPackets[nChannelID])
     /(nCurrTicks - ptPacket->nPrevTicks[nChannelID]);

    logMsg("%s %5d,channel %d:rate %d p/s,packets %d.\n",ptCaller->pchFuncName,
     ptCaller->nLine,nChannelID,ptPacket->nPacketRate[nChannelID],ptPacket->nPackets[nChannelID]);

    ptPacket->nPrevTicks[nChannelID]  = 0;
    ptPacket->nInterval[nChannelID]  = 0;
   }
  }
 }
}

void PacketRatePrint(int nInterval/*second*/)
{
 NW_INT32 nCaller;
 NW_INT32 nChannel;
 
 for (nCaller = 0; nCaller < g_nCallers; nCaller++)
 { 
  for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)
  {
   g_tPacket[nCaller].nInterval[nChannel] = nInterval;
  }
 }
}
#endif

发表于 @ 2006年12月11日 18:29:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:从软件角度看央视“赢在中国”节目的那套投票系统 | 新一篇:程序员的几个思维惯性

  • 发表评论
  • 评论内容:
  •  
Copyright © embeddedsoft
Powered by CSDN Blog