# log **Repository Path**: tlyd/log ## Basic Information - **Project Name**: log - **Description**: 单片机,linux平台打印调试,支持输出到串口,标准输出,文件 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-07-29 - **Last Updated**: 2023-08-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 功能: 1. - [x] 支持打印输出到文件、标准输出 2. - [x] 分级打印,过滤,定制 3. - [x] 打印信息能区分项目/进程,支持进程打印到不同日志文件 4. - [x] 支持分级颜色输出到标准输出 5. - [x] 可被多方同时调用,分项目配置和模块定制 6. - [x] 可在日志文件超过一定大小时,自动备份 7. - [x] 支持打印到串口 8. - [x] 包含**头部信息**和**打印内容**两部分,**打印内容**前的信息属于**头部信息** 9. - [x] 只给**打印内容**颜色输出,**头部信息**和日志文件中不输出颜色 # 版本介绍 dbg版:仅包含dbg.h一个文件,仅支持打印到标准输出 调试打印效果
log类型:模块名:文件(所在行):函数 打印内容
image-20210822152915705 log版:包含`log.h`、`log.c`、`sem.h`、`sem.c` 四个文件,仅支持写入日志文件 log版由宏`LOG_FILE_BAK`决定是否备份。不需要备份时,可省去`sem.h`、`sem.c` 两个文件 日志输出效果
[日期时间] log类型:模块名:文件(所在行):函数 打印内容
image-20210822153152292 # 推荐使用 1. 打印到标准输出,需要`dbg.h`一个文件 2. 打印到日志文件,需要`log.h`、`log.c`、`sem.h`、`sem.c` 3. dbg版和log版完全独立,可同时调用 ## 用法: ### dbg版 调用头文件,添加模块私有配置,即可使用。 image-20210822012814092 ```c #include "dbg.h" char * dbg_module_prefix = "模块名称"; DBG_L_TYPE dbg_module_level = 打印等级;//建议: 开发时设DBG_L_DBG ,发行运行时设DBG_L_INF ``` ### log版 调用头文件,修改项目整体配置;调用初始化函数,修改模块私有配置,即可使用。
日志的项目配置
image-20210822153902072
日志的模块配置
```c #include "log.h" int main(void) { //log_module_init(LOG_L_DBG, "test0", "_test0"); //log_module_init(LOG_L_DBG, "test0", "_com"); //log_module_init(LOG_L_DBG,"test0",""); log_module_init(打印等级,"模块打印前缀","日志文件的模块前缀"); } ``` ## API: ```c DBG_NOC(); DBG_ERR(); DBG_WRN(); DBG_INF(); DBG_DBG(); log_module_init(); LOG_NOC(); LOG_ERR(); LOG_WRN(); LOG_INF(); LOG_DBG(); ``` # 使用示例 见code里的代码 test0.c、test1.c为包含main()的两个模块,引用头文件,初始化调试或日志的配置。 test_test.c是不包含main()的模块,被调用,不需要初始化调试或日志的配置,引用头文件即可使用相应API。 Makefile包含两个宏image-20210822202727080,分别是两版示例的开关。 # 开发过程中遇到问题 ## 问题1 ```c #include int main(int argc, char const *argv[]) { printf("DEBUG");//√ char * log_l = "DEBUG"; char log_l1[] = "DEBUG"; printf(log_l);//× printf(log_l1);//× printf("%s", log_l);//√ printf("%s", log_l1);//√ return 0; } ``` ```shell $ gcc test.c test.c: In function ‘main’: test.c:10:2: warning: format not a string literal and no format arguments [-Wformat-security] 10 | printf(log_l);//× | ^~~~~~ test.c:11:9: warning: format not a string literal and no format arguments [-Wformat-security] 11 | printf(log_l1);//× | ``` ## 问题2 文件读写方面,有系统库和C库实现,分为两版(fd版、fp版) 实际使用,C库(fp版)更快,但是fwrite不是原子操作(实验没有这种现象)。 [参考](https://blog.csdn.net/oscarjulia/article/details/72638060) 1、缓冲文件系统与非缓冲系统的区别 缓冲文件系统(fopen) :在内存为每个文件开辟一个缓存区,当执行读操作,从磁盘文件将数据读入内存缓冲区,装满后从内存缓冲区依次读取数据。写操作同理。 内存缓冲区的大小影响着实际操作外存的次数,缓冲区越大,操作外存的次数越少,执行速度快,效率高。缓冲区大小由机器而定。 借助文件结构体指针对文件管理,可读写字符串、格式化数据、二进制数据。 非缓冲文件系统(open):依赖操作系统功能对文件读写,不设文件结构体指针,只能读写二进制文件。 2、open属于低级IO,fopen属于高级IO 3、open返回文件描述符,属于用户态,读写需进行用户态与内核态切换。 fopen返回文件指针 4、open是系统函数,不可移植 fopen是标准C函数,可移植 5、一般用fopen打开普通文件,open打开设备文件 6、 如果顺序访问文件,fopen比open快 如果随机访问文件,open比fopen快 文件写入操作先采用系统库(write)实现(fd版),之后考虑采用C库(fwrite)实现(fp版) **C库实现后,优先使用C库实现的fp版,fd版只作为参考备用,不再更新优化。** # 颜色参考 编写[参考](https://blog.csdn.net/m_pfly_fish/article/details/118541894)、[参考](https://blog.csdn.net/Zhishuifuyue/article/details/115253669?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control) 、[颜色参考](https://blog.csdn.net/u013177084/article/details/79553872) ``` \033[显示方式;前景色;背景色m输出字符串\033[0m 或 \e[显示方式;前景色;背景色m输出字符串\033[0m ``` ![image-20210723150943042](README.assets/image-20210723150943042.png) image-20210821134948338 ![image-20220306001015743](README.assets/image-20220306001015743.png) 终端不同,`前景色(35)`可能显示为洋红或紫色,`显示方式(1)`可能显示为高亮或高亮加粗 Note:stderr,和stdout还有重要一点区别,stderr是没有缓冲的,它立即输出,而stdout默认是行缓冲,也就是它遇到‘\n’,才向外输出内容,如果你想stdout也实时输出内容,那就在输出语句后加上fflush(stdout),这样就能达到实时输出的效果。