# 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类型:模块名:文件(所在行):函数 打印内容
log版:包含`log.h`、`log.c`、`sem.h`、`sem.c` 四个文件,仅支持写入日志文件
log版由宏`LOG_FILE_BAK`决定是否备份。不需要备份时,可省去`sem.h`、`sem.c` 两个文件
日志输出效果
[日期时间] log类型:模块名:文件(所在行):函数 打印内容
# 推荐使用
1. 打印到标准输出,需要`dbg.h`一个文件
2. 打印到日志文件,需要`log.h`、`log.c`、`sem.h`、`sem.c`
3. dbg版和log版完全独立,可同时调用
## 用法:
### dbg版
调用头文件,添加模块私有配置,即可使用。
```c
#include "dbg.h"
char * dbg_module_prefix = "模块名称";
DBG_L_TYPE dbg_module_level = 打印等级;//建议: 开发时设DBG_L_DBG ,发行运行时设DBG_L_INF
```
### log版
调用头文件,修改项目整体配置;调用初始化函数,修改模块私有配置,即可使用。
日志的项目配置
日志的模块配置
```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包含两个宏
,分别是两版示例的开关。
# 开发过程中遇到问题
## 问题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
```


终端不同,`前景色(35)`可能显示为洋红或紫色,`显示方式(1)`可能显示为高亮或高亮加粗
Note:stderr,和stdout还有重要一点区别,stderr是没有缓冲的,它立即输出,而stdout默认是行缓冲,也就是它遇到‘\n’,才向外输出内容,如果你想stdout也实时输出内容,那就在输出语句后加上fflush(stdout),这样就能达到实时输出的效果。