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

2019-07-12 15:24发布

       通过打印日志定位排查问题,是嵌入式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 ",i+j); my_err("i-j = %d ",i-j); return 0; }  再次感谢谢谢 Z_Dream_ST 、alofm  两位博主!!! 其中有些异常没有考虑,仅示例基本功能,如有考虑不周的地方,还望指正。谢谢!