请实现UnitPrint.c中的信息输出接口,需要做到如下效果、要求:
1.全局变量g_UnitPrint控制是否交换界面打印,关闭时需要接口效率极高、即不做不必要的处理。
2.系统接口SysLogger、SysUdp可以改动,已打桩无需修改或可以简单修改去除告警。
3.实现UnitLogDebug、UnitLogInfo、UnitLogError,需要和使用printf的格式类似。假设UnitLogInfo、UnitLogError调用频率大部分情况下都不高,出现故障时可能设备已经重启,所以需要最终调用SysLogger记录到系统日志;
UnitLogDebug则调用频率很高不能调用记录系统日志;
UnitLogInfo、UnitLogError、UnitLogDebug最终都调用SysUdp接口实现实时抓包。
UnitLogInfo、UnitLogDebug需要考虑效率,没有必要SysUdp、界面打印等要求时,需要尽量少的做额外处理。
4.这些接口统一放在某头文件中作为模块内接口文件
5.UnitLogError需要额外记录到一静态表中。静态表需要满足如下要求:
(1).静态表最多记录8条信息,每条最大1K空间。
(2).来自同一行代码的记录只能占用1条信息空间,只保留最后一次的打印即可,需要记录同一行打印的总打印次数、无符号整型记录即可无效考虑溢出翻转。
(3).表满时,当前最新记录覆盖时间最早的一条。
(4).每条信息需要记录信息的记录年、月、日、时、分、秒、毫秒,以及对应位置的函数名、代码行数。
(5).需要考虑参数过长时记录静态表的防护。
【UnitLogError也有可能有频繁的业务调用、导致不能记录系统日志只能用静态表,但当前题目中未体现这点】
6.目标运行环境为linux系统。
7.不考虑系统重入性问题,即不用额外考虑并发问题。
部分提示:
#include <stdarg.h>
__FUNCTION__, __LINE__, __VA_ARGS__, va_list, vsnprintf。
时间处理参考1(linux系统库):
#include <sys/time.h>
struct timeval a,b;
char tmbuf[64];
gettimeofday(&a, NULL);
timercmp( &a, &b, > ); /*比较时间大小*/
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S",localtime(&a.tv_sec)); /*打印时间*/
printf( "[%s.%06ld]\n", tmbuf, a.tv_usec); /*打印微秒*/
时间处理参考2(linux系统库):
#include <sys/timeb.h>
#include <time.h>
struct timeb a;
ftime( &a ); /*取当前时间*/
struct tm *pTM = localtime( &a.time ); /*打印时间前的转换处理*/
printf( "[%04d-%02d-%02d %02d:%02d:%02d.%03d]\n",
pTM->tm_year+1900, pTM->tm_mon + 1, pTM->tm_mday,pTM->tm_hour, pTM->tm_min, pTM->tm_sec, pSE->timep.millitm);
/*打印时间*/
时间处理参考3(C语言库,精确到秒):
#include <time.h>
time_t first;
time_t second;
struct tm *gmt;
time(&first); /*取当前时间*/
time(&second); /*取当前时间*/
difftime(second,first); /*取时间差,单位为秒*/
gmt=gmtime(&first);
printf( "[%04d-%02d-%02d %02d:%02d:%02d]\n",
pTM->tm_year+1900, pTM->tm_mon + 1, pTM->tm_mday,pTM->tm_hour, pTM->tm_min, pTM->tm_sec);
/*打印时间*/
UnitPrint.h
#ifndef _UNIT_LOG_H_
#define _UNIT_LOG_H_
#define UNIT_LOG_LEVEL_ERROR 0
#define UNIT_LOG_LEVEL_INFO 1
#define UNIT_LOG_LEVEL_DEBUG 2
void UnitLogInit( void );
void _UnitLog(const char *file, const char * func, const unsigned int line, short level, unsigned char shellPrint, const char *str, ...);
#define UnitLogDebug(...) _UnitLog(__FILE__, __FUNCTION__, __LINE__, UNIT_LOG_LEVEL_DEBUG, 0, __VA_ARGS__)
#define UnitLogInfo(...) _UnitLog(__FILE__, __FUNCTION__, __LINE__, UNIT_LOG_LEVEL_INFO , 0, __VA_ARGS__)
#define UnitLogError(...) _UnitLog(__FILE__, __FUNCTION__, __LINE__, UNIT_LOG_LEVEL_ERROR, 0, __VA_ARGS__)
extern unsigned char g_UnitPrint;
void ShowUnitErrorTable(void);
#endif
UnitPrint.c
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include "UnitPrint.h"
#define BOOL char
#define FALSE 0
#define TRUE 1
void SysLogger(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
void SysUdp(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
int IsUdpOpened(void) { return 0;/*No need to do*/}
#define MAXSAVEEXCEPTION 8
typedef struct
{
unsigned int line;
unsigned int count;
time_t tt;
char strFunName[32];
char strReason[256];
}UnitException;
UnitException G_UnitException[MAXSAVEEXCEPTION];
static int G_UnitExceptionInit = 0;
int UnitGetExceptionIndex( const char *strFunName, unsigned int line)
{
int i = 0;
int iTimeMin = 0;
UnitException *pSE;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &(G_UnitException[i]);
if( line == pSE->line &&
strcmp( strFunName, pSE->strFunName ) == 0 )
{
return i;
}
if( difftime( G_UnitException[iTimeMin].tt, (pSE->tt)) > 0 )
{
iTimeMin = i;
}
}
return iTimeMin;
}
void UnitLogInit( void )
{
if (0 == G_UnitExceptionInit)
{
memset(G_UnitException,0,sizeof(G_UnitException));
G_UnitExceptionInit = 1;
}
}
void ShowUnitErrorTable(void)
{
char tmbuf[32];
UnitException *pSE;
int i = 0;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &G_UnitException[i];
if( 0 == strlen(pSE->strFunName))
{
break;
}
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S",gmtime(&pSE->tt));
printf( "[%s]%s[%d] %s\n", tmbuf, pSE->strFunName, pSE->count, pSE->strReason );
}
}
unsigned char g_UnitPrint = 0;
static char UnitLogBuf[256];
void _UnitLog(const char *file, const char * func, const unsigned int line, short level, unsigned char shellPrint, const char *str, ...)
{
int iRe = 0;
UnitException *pSE = NULL;
va_list argptr;
if ((0 == shellPrint) && (0 == g_UnitPrint) && (level > UNIT_LOG_LEVEL_INFO) && (0 == IsUdpOpened()))
{
return;
}
va_start (argptr,str);
vsnprintf(UnitLogBuf ,sizeof(UnitLogBuf) , str,argptr);
va_end (argptr);
if (shellPrint || g_UnitPrint)
{
printf("%s\n",UnitLogBuf);
}
if (UNIT_LOG_LEVEL_ERROR == level)
{
iRe = UnitGetExceptionIndex( func, line );
pSE = &G_UnitException[iRe];
pSE->line = line;
pSE->count++;
time(&pSE->tt);
snprintf( pSE->strFunName,sizeof( pSE->strFunName),func);
snprintf(pSE->strReason ,sizeof(pSE->strReason) , UnitLogBuf);
}
if (level <= UNIT_LOG_LEVEL_INFO )
{
SysLogger(file, func, line, UnitLogBuf);
}
SysUdp(file, func, line, UnitLogBuf);
}
int main(void)
{
int i=0;
UnitLogInit();
g_UnitPrint = 1;
UnitLogDebug("This is Debug:%d",i++);
UnitLogInfo("This is Info:%d",i++);
UnitLogError("This is Error:%d",i++);
UnitLogError("This is Error:%d",i++);
g_UnitPrint = 0;
UnitLogError("This is Error:%d",i++);
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error1:%d",i);
}
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error2:%d",i);
UnitLogError("This is Error3:%d",i);
UnitLogError("This is Error4:%d",i);
UnitLogError("This is Error5:%d",i);
UnitLogError("This is Error6:%d",i);
}
ShowUnitErrorTable();
return 0;
}
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <sys/timeb.h>
#include "UnitPrint.h"
#define BOOL char
#define FALSE 0
#define TRUE 1
void SysLogger(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
void SysUdp(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
int IsUdpOpened(void) { return 0;/*No need to do*/}
#define MAXSAVEEXCEPTION 8
typedef struct
{
unsigned int line;
unsigned int count;
struct timeb timep;
char strFunName[32];
char strReason[256];
}UnitException;
UnitException G_UnitException[MAXSAVEEXCEPTION];
static int G_UnitExceptionInit = 0;
BOOL IsTimeSmall( struct timeb in_time1, struct timeb in_time2 )
{
if( in_time1.time > in_time2.time ||
((in_time1.time == in_time2.time) &&
(in_time1.millitm > in_time2.millitm)) )
{
return FALSE;
}
return TRUE;
}
int UnitGetExceptionIndex( const char *strFunName, int line)
{
int i = 0;
int iTimeMin = 0;
UnitException *pSE;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &(G_UnitException[i]);
if( line == pSE->line &&
strcmp( strFunName, pSE->strFunName ) == 0 )
{
return i;
}
if( FALSE == IsTimeSmall( G_UnitException[iTimeMin].timep, pSE->timep ) )
{
iTimeMin = i;
}
}
return iTimeMin;
}
void UnitLogInit( void )
{
if (0 == G_UnitExceptionInit)
{
memset(G_UnitException,0,sizeof(G_UnitException));
G_UnitExceptionInit = 1;
}
}
void ShowUnitErrorTable(void)
{
struct tm *pTM;
UnitException *pSE;
int i = 0;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &G_UnitException[i];
if( 0 == strlen(pSE->strFunName))
{
break;
}
pTM = localtime( &pSE->timep.time );
if (NULL != pTM)
{
printf( "[%04d-%02d-%02d %02d:%02d:%02d.%03d]%s[%d] %s\n",
pTM->tm_year+1900, pTM->tm_mon + 1, pTM->tm_mday,
pTM->tm_hour, pTM->tm_min, pTM->tm_sec, pSE->timep.millitm,
pSE->strFunName, pSE->count, pSE->strReason );
}
}
}
unsigned char g_UnitPrint = 0;
static char UnitLogBuf[256];
void _UnitLog(const char *file, const char * func, const unsigned int line, short level, unsigned char shellPrint, const char *str, ...)
{
int iRe = 0;
UnitException *pSE = NULL;
va_list argptr;
if ((0 == shellPrint) && (0 == g_UnitPrint) && (level > UNIT_LOG_LEVEL_INFO) && (0 == IsUdpOpened()))
{
return;
}
va_start (argptr,str);
vsnprintf(UnitLogBuf ,sizeof(UnitLogBuf) , str,argptr);
va_end (argptr);
if (shellPrint || g_UnitPrint)
{
printf("%s\n",UnitLogBuf);
}
if (UNIT_LOG_LEVEL_ERROR == level)
{
iRe = UnitGetExceptionIndex( func, line );
pSE = &G_UnitException[iRe];
pSE->line = line;
pSE->count++;
ftime( &(pSE->timep) );
snprintf( pSE->strFunName,sizeof( pSE->strFunName),func);
snprintf(pSE->strReason ,sizeof(pSE->strReason) , UnitLogBuf);
}
if (level <= UNIT_LOG_LEVEL_INFO )
{
SysLogger(file, func, line, UnitLogBuf);
}
SysUdp(file, func, line, UnitLogBuf);
}
int main(void)
{
int i=0;
UnitLogInit();
g_UnitPrint = 1;
UnitLogDebug("This is Debug:%d",i++);
UnitLogInfo("This is Info:%d",i++);
UnitLogError("This is Error:%d",i++);
UnitLogError("This is Error:%d",i++);
g_UnitPrint = 0;
UnitLogError("This is Error:%d",i++);
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error1:%d",i);
}
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error2:%d",i);
UnitLogError("This is Error3:%d",i);
UnitLogError("This is Error4:%d",i);
UnitLogError("This is Error5:%d",i);
UnitLogError("This is Error6:%d",i);
}
ShowUnitErrorTable();
return 0;
}
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <sys/timeb.h>
#include "UnitPrint.h"
#define BOOL char
#define FALSE 0
#define TRUE 1
void SysLogger(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
void SysUdp(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
int IsUdpOpened(void) { return 0;/*No need to do*/}
#define MAXSAVEEXCEPTION 8
typedef struct
{
unsigned int line;
unsigned int count;
struct timeb timep;
char strFunName[32];
char strReason[256];
}UnitException;
UnitException G_UnitException[MAXSAVEEXCEPTION];
static int G_UnitExceptionInit = 0;
BOOL IsTimeSmall( struct timeb in_time1, struct timeb in_time2 )
{
if( in_time1.time > in_time2.time ||
((in_time1.time == in_time2.time) &&
(in_time1.millitm > in_time2.millitm)) )
{
return FALSE;
}
return TRUE;
}
int UnitGetExceptionIndex( const char *strFunName, unsigned int line)
{
int i = 0;
int iTimeMin = 0;
UnitException *pSE;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &(G_UnitException[i]);
if( line == pSE->line &&
strcmp( strFunName, pSE->strFunName ) == 0 )
{
return i;
}
if( FALSE == IsTimeSmall( G_UnitException[iTimeMin].timep, pSE->timep ) )
{
iTimeMin = i;
}
}
return iTimeMin;
}
void UnitLogInit( void )
{
if (0 == G_UnitExceptionInit)
{
memset(G_UnitException,0,sizeof(G_UnitException));
G_UnitExceptionInit = 1;
}
}
void ShowUnitErrorTable(void)
{
char tmbuf[32];
UnitException *pSE;
int i = 0;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &G_UnitException[i];
if( 0 == strlen(pSE->strFunName))
{
break;
}
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S",localtime(&pSE->timep.time));
printf( "[%s.%03d]%s[%d] %s\n", tmbuf, pSE->timep.millitm, pSE->strFunName, pSE->count, pSE->strReason );
}
}
unsigned char g_UnitPrint = 0;
static char UnitLogBuf[256];
void _UnitLog(const char *file, const char * func, const unsigned int line, short level, unsigned char shellPrint, const char *str, ...)
{
int iRe = 0;
UnitException *pSE = NULL;
va_list argptr;
if ((0 == shellPrint) && (0 == g_UnitPrint) && (level > UNIT_LOG_LEVEL_INFO) && (0 == IsUdpOpened()))
{
return;
}
va_start (argptr,str);
vsnprintf(UnitLogBuf ,sizeof(UnitLogBuf) , str,argptr);
va_end (argptr);
if (shellPrint || g_UnitPrint)
{
printf("%s\n",UnitLogBuf);
}
if (UNIT_LOG_LEVEL_ERROR == level)
{
iRe = UnitGetExceptionIndex( func, line );
pSE = &G_UnitException[iRe];
pSE->line = line;
pSE->count++;
ftime( &(pSE->timep) );
snprintf( pSE->strFunName,sizeof( pSE->strFunName),func);
snprintf(pSE->strReason ,sizeof(pSE->strReason) , UnitLogBuf);
}
if (level <= UNIT_LOG_LEVEL_INFO )
{
SysLogger(file, func, line, UnitLogBuf);
}
SysUdp(file, func, line, UnitLogBuf);
}
int main(void)
{
int i=0;
UnitLogInit();
g_UnitPrint = 1;
UnitLogDebug("This is Debug:%d",i++);
UnitLogInfo("This is Info:%d",i++);
UnitLogError("This is Error:%d",i++);
UnitLogError("This is Error:%d",i++);
g_UnitPrint = 0;
UnitLogError("This is Error:%d",i++);
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error1:%d",i);
}
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error2:%d",i);
UnitLogError("This is Error3:%d",i);
UnitLogError("This is Error4:%d",i);
UnitLogError("This is Error5:%d",i);
UnitLogError("This is Error6:%d",i);
}
ShowUnitErrorTable();
return 0;
}
#include "stdio.h"
#include "string.h"
#include <time.h>
#include <stdarg.h>
#include <sys/time.h>
#include "UnitPrint.h"
#define BOOL char
#define FALSE 0
#define TRUE 1
void SysLogger(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
void SysUdp(const char *file, const char * func, const int line,char * log) /*Can change this Interface as you need*/
{ /*No need to do*/}
int IsUdpOpened(void) { return 0;/*No need to do*/}
#define MAXSAVEEXCEPTION 8
typedef struct
{
unsigned int line;
unsigned int count;
struct timeval timeV;
char strFunName[32];
char strReason[256];
}UnitException;
UnitException G_UnitException[MAXSAVEEXCEPTION];
static int G_UnitExceptionInit = 0;
int UnitGetExceptionIndex( const char *strFunName, unsigned int line)
{
int i = 0;
int iTimeMin = 0;
UnitException *pSE;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &(G_UnitException[i]);
if( line == pSE->line &&
strcmp( strFunName, pSE->strFunName ) == 0 )
{
return i;
}
if( timercmp( &G_UnitException[iTimeMin].timeV, &(pSE->timeV), > ) )
{
iTimeMin = i;
}
}
return iTimeMin;
}
void UnitLogInit( void )
{
if (0 == G_UnitExceptionInit)
{
memset(G_UnitException,0,sizeof(G_UnitException));
G_UnitExceptionInit = 1;
}
}
void ShowUnitErrorTable(void)
{
char tmbuf[32];
UnitException *pSE;
int i = 0;
for( i = 0; i < MAXSAVEEXCEPTION; i++ )
{
pSE = &G_UnitException[i];
if( 0 == strlen(pSE->strFunName))
{
break;
}
strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S",localtime(&pSE->timeV.tv_sec));
printf( "[%s.%06ld]%s[%d] %s\n", tmbuf, pSE->timeV.tv_usec, pSE->strFunName, pSE->count, pSE->strReason );
}
}
unsigned char g_UnitPrint = 0;
static char UnitLogBuf[256];
void _UnitLog(const char *file, const char * func, const unsigned int line, short level, unsigned char shellPrint, const char *str, ...)
{
int iRe = 0;
UnitException *pSE = NULL;
va_list argptr;
if ((0 == shellPrint) && (0 == g_UnitPrint) && (level > UNIT_LOG_LEVEL_INFO) && (0 == IsUdpOpened()))
{
return;
}
va_start (argptr,str);
vsnprintf(UnitLogBuf ,sizeof(UnitLogBuf) , str,argptr);
va_end (argptr);
if (shellPrint || g_UnitPrint)
{
printf("%s\n",UnitLogBuf);
}
if (UNIT_LOG_LEVEL_ERROR == level)
{
iRe = UnitGetExceptionIndex( func, line );
pSE = &G_UnitException[iRe];
pSE->line = line;
pSE->count++;
gettimeofday(&(pSE->timeV), NULL);
snprintf( pSE->strFunName,sizeof( pSE->strFunName),func);
snprintf(pSE->strReason ,sizeof(pSE->strReason) , UnitLogBuf);
}
if (level <= UNIT_LOG_LEVEL_INFO )
{
SysLogger(file, func, line, UnitLogBuf);
}
SysUdp(file, func, line, UnitLogBuf);
}
int main(void)
{
int i=0;
UnitLogInit();
g_UnitPrint = 1;
UnitLogDebug("This is Debug:%d",i++);
UnitLogInfo("This is Info:%d",i++);
UnitLogError("This is Error:%d",i++);
UnitLogError("This is Error:%d",i++);
g_UnitPrint = 0;
UnitLogError("This is Error:%d",i++);
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error1:%d",i);
}
ShowUnitErrorTable();
puts("");
for(i=0;i<20;i++)
{
UnitLogError("This is Error2:%d",i);
UnitLogError("This is Error3:%d",i);
UnitLogError("This is Error4:%d",i);
UnitLogError("This is Error5:%d",i);
UnitLogError("This is Error6:%d",i);
}
ShowUnitErrorTable();
return 0;
}