嵌入式linux 打印调试log封装函数

       通过打印日志定位排查问题,是嵌入式linux c常用的方法。常见的打印日志方式有: printf打印到前台、fprintf到文件中、打印到syslog(网上介绍文章较多,不再赘述)中。这里介绍一种我在项目中将三者结合起来使用的方式,请大家提供宝贵意见。

     参见文章:https://blog.csdn.net/z_dream_st/article/details/77418073; 

                   :https://bbs.csdn.net/topics/390841785  

     谢谢 Z_Dream_ST 、alofm  的分享!!! 

     printf是程序在前台运行时,常用的方法,适用于前期调试阶段;syslog有分机打印的机制,并且打印到循环队列中方便程序后台运行时通过logread  -f 查看,也可以开启保存到日志文件功能。本来syslog的功能已经很完美了,但在项目使用过程中发现syslog有时会漏掉打印消息,尤其是打印的数据特别大的时候,最容易打印不全或漏打数据。因能力有限,没有看syslog的源码定位问题,于是想到了将少量的但非常重要的信息通过fprintf打印到文件中。就产生了文章开头所说将三者结合起来使用的方式,闲言少叙,示例代码如下:

#include 
#include 
#include 
#include 

#include 

#include 
#include 


/*syslog  等级
 * LOG_EMERG   0   紧急状态
 * LOG_ALERT   1   必须立即修复状态
 * LOG_CRIT    2   严重状态
 * LOG_ERR     3   出错状态
 * LOG_WARNING 4   警告状态
 * LOG_NOTICE  5   正常,但重要的状态
 * LOG_INFO    6   信息性消息
 * LOG_DEBUG   7   调试消息
 */

// 主要是因为使用到了  vprintf 、vfprintf、vsyslog等函数,在x86的ubuntu14.04中,不能连续使用,需要拷贝一份 va_list 参数
// vfprintf 连续使用时,需要复制一份, 本文主要是 vprintf、vfprintf的连续使用
// 参见 :https://bbs.csdn.net/topics/390841785  中2楼所说 ,感谢 alofm 博主
// 本人使用的嵌入式平台是  TI-am3354 
#define x86 1

#define PROGRAM "[process name] "

void my_syslog(unsigned int lev,const char *msg,...);

#define mypfdbg
#ifdef mypfdbg
#define my_debug(format,...)  my_syslog(LOG_DEBUG, PROGRAM  "[%s:%d] " format,__FILE__,__LINE__,##__VA_ARGS__)
#else
#define my_debug(format,...)
#endif

#define my_info(format,...)  my_syslog(LOG_INFO, PROGRAM  "[%s:%d] " format,__FILE__,__LINE__,##__VA_ARGS__)
#define my_err(format,...)  my_syslog(LOG_ERR, PROGRAM  "[%s:%d] " format,__FILE__,__LINE__,##__VA_ARGS__)


unsigned char flag_pf = 1;  //程序是否前台运行的标记,通过命令行传入参数确地是否前台运行,并修改
unsigned char dbg_lev = 7;  //syslog的打印级别,通过命令行传入参数修改 
FILE *fp = NULL;


int init_file_point(void)
{
	if(NULL==fp)
		fp = fopen("/home/mydir/test.log","a+");

	if(NULL!=fp)
		return 0;
	else
		return -1;
}

// 添加时间标记前缀
static void add_time_tag(char *dst,int bufsize,const char *format,...)
{
	time_t now;
	time(&now);
	struct tm *local;

	local = localtime(&now);
	strftime(dst,bufsize,"%m-%d %T ",local);

        strcat(dst,format);
}


void my_syslog(unsigned int lev,const char *msg,...)
{
	int len = 0,mal_flag = 0, bufsize = 0;
	char *ptr = NULL;
	char buf[512] = {0};

	if(lev<=dbg_lev)    //默认的打印等级
	{
		va_list ap;
		openlog("tag",LOG_PID,LOG_USER);
		va_start(ap,msg);

		if( (flag_pf) || (lev==LOG_ERR) )
		{
			len = strlen(msg);
			if(len<(512-40))
			{
				ptr = buf;
				bufsize = 512;
			}
			else
			{
				mal_flag = 1;
				bufsize = len + 40;
				ptr = (char *)malloc(bufsize); 
				bzero(ptr,bufsize);
			}
			add_time_tag(ptr,bufsize,msg);	
		}

// 在嵌入式linux中不需要下面条件编译的代码,如果没有下面条件编译部分代码,在ubuntu中运行时会段错误,具体原因未深入研究
#ifdef x86
		va_list map,myap;
		va_copy(map,ap);
		va_copy(myap,ap);
#endif

		if(flag_pf)  //如果是前台运行,实现printf功能  
			vprintf(ptr,ap);

		if( (NULL != fp) && (lev==LOG_ERR)) //如果级别是错误,同时打印到File流文件
#ifdef x86
			vfprintf(fp,ptr,map);
#else
			vfprintf(fp,ptr,ap); // 在嵌入式平台中只需要这行就行
#endif

		if(1 == mal_flag)
			free(ptr);
#ifdef x86
		vsyslog(lev,msg,myap);   //syslog有时间前缀,所有不使用增加前缀的ptr指针
#else
		vsyslog(lev,msg,ap);   //syslog有时间前缀,所有不使用增加前缀的ptr指针
#endif
		va_end(ap);
		closelog();
	}
}

int main(int argc, const char *argv[])
{

	init_file_point();
	int i = 8, j = 5;

	my_debug("i+j = %d\n",i+j);
	my_err("i-j = %d\n",i-j);

	return 0;
}

 再次感谢谢谢 Z_Dream_ST 、alofm  两位博主!!!

 其中有些异常没有考虑,仅示例基本功能,如有考虑不周的地方,还望指正。谢谢!












你可能感兴趣的:(嵌入式linux,调试日志)