Linux-C 简单的C语言日志库
Linux-C 简单的C语言日志库
一、简述
记--C语言实现的简单的日志库,可循环覆盖滚动记录日志文件,达到限制就另记一个日志文件,可控制日志文件个数,可控制日志文件大小。
打包下载:外链:https://wwm.lanzouv.com/b0cazvkwb 密码:de1r
二、测试代码
clog.h文件
/** clog.h** Created on: 2022-6-11* Author: liang*/#ifndef _CLOG_H_
#define _CLOG_H_#ifdef __cplusplus
extern "C" {
#endif#include <limits.h>typedef enum {CLOG_ACK_FAIL = -1, //操作失败CLOG_ACK_OK = 0, //操作成功
} CLogAck_e;typedef struct {int fd;int fileCnt; //滚动记录多少个日志文件, 如5个日志文件 a.log(当前正在记录的文件) a.log.1 a.log.2 a.log.3 a.log.4 按时间排序, 最新-->最旧unsigned int currSize; //用户无需关心,当前日志文件大小unsigned int maxSize; //一个日志文件的大小,满了之后另记一个文件char path[PATH_MAX]; //用户无需关心,日志文件路径int bufSize; //每次写入日志数据最大的大小,void *buf; //用户无需关心, 每次写入日志数据的缓冲区
} CLogger_t;/******************************************
* 函数: CLogInitLogger
* 功能: 初始化日志记录器
* 参数: CLogger_t *logger:
* const char* path:
* 输入:
* 输出:
* 返回: int 成功返回:CLOG_ACK_OK;其它返回:
* 说明: @xxx 2022.06.12 周日
******************************************/
CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path);/******************************************
* 函数: CLogUninitLogger
* 功能: 释放日志记录器
* 参数: CLogger_t *logger:
* 输入:
* 输出:
* 返回: void
* 说明: @xxx 2022.06.12 周日
******************************************/
void CLogUninitLogger(CLogger_t *logger);/******************************************
* 函数: CLog
* 功能: 记录日志信息接口
* 参数: CLogger_t *logger:
* const char *fmt:
* ...:
* 输入:
* 输出:
* 返回: int 成功返回:写入字节数;其它返回:
* 说明: @xxx 2022.06.12 周日
******************************************/
int CLog(CLogger_t *logger, const char *fmt, ...);#ifdef __cplusplus
}
#endif#endif /* _CLOG_H_ */
clog.c文件
/** clog.c** Created on: 2022-6-11* Author: liang*/#include <fcntl.h>
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "clog.h"#if 1
#define LOGD(fmt, args...) printf("[%s-%s-%d] " fmt, __FILE__, __func__, __LINE__, ##args)
#define LOGE(info) perror(info)
#else
#define LOGD(fmt, args...)
#define LOGE(info)
#endif//滚动日志文件,达到限制就另记一个日志文件
static void RollLogFile(CLogger_t *logger)
{int i;off_t size;if (logger->currSize >= logger->maxSize) {LOGD("currSize:%u, maxSize=%u\r\n", logger->currSize, logger->maxSize);//再次大小确认size = lseek(logger->fd, 0, SEEK_END);logger->currSize = (unsigned int)size>=0?size:0;if (logger->currSize < logger->maxSize) {return;}//开始滚动日志char file1[PATH_MAX] = {0};char file2[PATH_MAX] = {0};for (i = logger->fileCnt-2; 0 < i; i--) {snprintf(file1, sizeof(file1), "%s.%d", logger->path, i);snprintf(file2, sizeof(file2), "%s.%d", logger->path, i+1);if (F_OK == access(file2, F_OK)) {unlink(file2);LOGD("unlink %s\r\n", file2);}rename(file1, file2);//rename重命名不会更改文件的修改时间LOGD("rename %s %s\r\n", file1, file2);}snprintf(file2, sizeof(file2), "%s.1", logger->path);if (F_OK == access(file2, F_OK)) {unlink(file2);LOGD("unlink %s\r\n", file2);}if (0 <= logger->fd) {close(logger->fd);logger->fd = -1;}rename(logger->path, file2);LOGD("rename %s %s\r\n", logger->path, file2);logger->currSize = 0;logger->fd = open(logger->path, O_CREAT|O_RDWR|O_APPEND, 0666);}
}//初始化日志记录器
CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path)
{
#define DEFAULT_LOG_FILE_COUNT 5
#define DEFAULT_LOG_ONE_FILE_SIZE (2*1024*1024) //2M
#define DEFAULT_LOG_BUF_MAX_LEN (2048)int fd;off_t size;fd = open(path, O_CREAT|O_RDWR|O_APPEND, 0666);if (0 > fd) {LOGE("open fail error:");return CLOG_ACK_FAIL;}logger->bufSize = (0 >= logger->bufSize)?DEFAULT_LOG_BUF_MAX_LEN:logger->bufSize;logger->buf = malloc(logger->bufSize);if (NULL == logger->buf) {LOGD("malloc fail\r\n");close(fd);return CLOG_ACK_FAIL;}size = lseek(fd, 0, SEEK_END);logger->fd = fd;logger->fileCnt = (0 >= logger->fileCnt)?DEFAULT_LOG_FILE_COUNT:logger->fileCnt;logger->maxSize = (0 >= logger->maxSize)?DEFAULT_LOG_ONE_FILE_SIZE:logger->maxSize;logger->currSize = (unsigned int)size>=0?size:0;memset(logger->path, 0x0, sizeof(logger->path));strncpy(logger->path, path, sizeof(logger->path));RollLogFile(logger);return CLOG_ACK_OK;
}//释放日志记录器
void CLogUninitLogger(CLogger_t *logger)
{if (0 < logger->fd) {close(logger->fd);logger->fd = -1;}if (NULL != logger->buf) {free(logger->buf);}memset(logger, 0x0, sizeof(CLogger_t));
}//记录日志信息接口
int CLog(CLogger_t *logger, const char *fmt, ...)
{int wLen;int buf_len;int tmp_len;time_t timep = {0};struct tm tmTime = {0};time(&timep);gmtime_r(&timep, &tmTime);snprintf(logger->buf, logger->bufSize, "#%02d-%02d-%02d %02d:%02d:%02d->",(1900+tmTime.tm_year), tmTime.tm_mon+1, tmTime.tm_mday,tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);buf_len = strlen(logger->buf);va_list arglist;va_start(arglist, fmt);wLen = vsnprintf((char*)logger->buf+buf_len, logger->bufSize-buf_len, fmt, arglist);va_end(arglist);if (0 < wLen) {buf_len += wLen;} else {wLen = buf_len;}tmp_len = logger->maxSize - logger->currSize;//剩余空间, 可能会分两次写入if (0 < tmp_len && buf_len > tmp_len) {wLen = tmp_len;}wLen = write(logger->fd, logger->buf, wLen);if (0 < wLen) {logger->currSize += wLen;tmp_len = wLen;//记录已写入字节wLen = buf_len - wLen;RollLogFile(logger);if (0 < wLen) {//还有要写入的wLen = write(logger->fd, (char*)logger->buf+tmp_len, wLen);if (0 < wLen) {logger->currSize += wLen;wLen += tmp_len;}RollLogFile(logger);}} else {RollLogFile(logger);}return wLen;
}
demo.c文件
#include <stdio.h>
#include <time.h>
#include "clog.h"int main(int argc, char *argv[])
{int ret;int count = 50;//配置最多记录多少个日志文件,每个日志文件大小CLogger_t logger = {.fileCnt = 5, //5个日志文件.maxSize = 1024, //每个日志文件大小};//初始化日志记录器ret = CLogInitLogger(&logger, "test.log");if (CLOG_ACK_OK != ret) {printf("CLogInitLogger fail, ret:%d\r\n", ret);return -1;}//测试写日志 while (count--) {CLog(&logger, "Hello CLog! time: %ld, count: %d\r\n", time(NULL), count);}//释放日志记录器CLogUninitLogger(&logger);return 0;
}
三、测试结果
编译:gcc demo.c clog.c -o demo -Wall
测试例子:最多记录5个日志文件,每个日志文件1024字节。test.log日志为当前正在记录的日志。
Linux-C 简单的C语言日志库相关推荐
- 【C/C++开源库】单片机/嵌入式中的C语言日志库
日志系统在系统开发和调整过程中的重要性,大家应该都清楚,特别是项目出问题之后,却没有日志可以帮忙定位问题,就非常令人痛苦. 因为我们不可能一直通过调试器去单步调试程序,所以设备的运行日志显得尤为重要. ...
- 【CC++开源库】单片机嵌入式中的C语言日志库
日志系统在系统开发和调整过程中的重要性,大家应该都清楚,特别是项目出问题之后,却没有日志可以帮忙定位问题,就非常令人痛苦. 因为我们不可能一直通过调试器去单步调试程序,所以设备的运行日志显得尤为重要. ...
- Go语言日志库zerolog
Go语言日志库zerolog 在开发大型项目时,将日志进行结构化以提高可读性.可查询性和速度是非常重要的. 为什么你选择不使用其他结构化日志库,如logrus或zap? Zerolog 是一款高性能且 ...
- linux 系统常用的C语言函数库
2019独角兽企业重金招聘Python工程师标准>>> pkg-config --list-all 查看系统己安装库(yum install pkgconfig sudo ap ...
- 日志库 winston 的学习笔记 - 创建一个使用 winston 的 Node.js 应用
winston 被设计为一个简单且通用的日志库,支持多种传输. 传输本质上是日志的存储设备. 每个 winston 记录器都可以在不同级别配置多个存储渠道.例如,人们可能希望将错误日志存储在持久的远程 ...
- Rust应用调用C语言动态库
外部功能接口FFI 虽然高级(脚本)编程语言的功能丰富,表达能力强,但对底层的一些特殊操作的支持并不完善,就需要以其他编程语言来实现.调用其他编程语言的接口,被称为Foreign Function I ...
- go 日志库 zap
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.zap是什么? 二.使用步骤 1.基本使用 2.写入文件 前言 zap日志 Zap提供了两种类型的日志记录器-Su ...
- 基于Linux C的简单日志库
最近由于接手了几个小的开发项目,一直苦于寻找一个调用简单,方便调试,占用资源小的日志库,因为我大部分的嵌入式开发项目都是C/C++的开发.就想着做一个小的日志调用接口C/C++库.最近有时间整理一下. ...
- 基于C语言Ncurse库和链表的简单贪吃蛇小游戏
参考:基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者:三速何时sub20 发布时间:2020-09-29 10:23:51 网址:https://blog.csdn.net/weixin_44 ...
最新文章
- 2个月精通Python爬虫——3大爬虫框架+6场实战+分布式爬虫,包教包会
- python爬虫简单实例-最简单的Python爬虫案例,看得懂说明你已入门,附赠教程
- 【Python基础】Python 面向对象编程(上篇)
- MT6580启动流程
- (转)字典树原理+实现
- Java IO7:管道流、对象流
- SizeOf相关代码
- 面料经纬向、正反面判别方法
- 少年,别再收藏文章了!
- js,jquery的数字型字符串变量比较大小
- 【c语言课程设计】C语言校园卡管理系统
- 基于Systemview的巴克码识别器设计
- 系统建模与仿真 - 电子书下载(高清版PDF格式+EPUB格式)
- 扩展有限元程序matlab,Abaqus中扩展有限元(XFEM)功能简介
- 取整函数access_ACCESS常用函数总结
- Visual Studio Code安装及设置
- Javascript前端模块化
- 【UE4】WebUI插件实现HTML透明区域事件穿透响应
- 为马来西亚航空失联飞机祈福~~
- 一种计算标准差的高效方法:Welford迭代法
热门文章
- 一键批量PDF转换成图片文件
- 计算机操作系统学习笔记 第一章、操作系统概论
- MSDC 4.3 接口规范(5)
- WIN10 x64搭建OLLVM4.0 android NDK 编译环境跨坑指南
- 【demo记录】百度地图获取当前所在城市
- DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver File List
- Java将汉字转为拼音
- 2021南昌市地区高考成绩排名查询,2021南昌中小学国编成绩排名/分数线
- STM32怎样实现延时?
- html背景斜线,巧妙的实现 CSS 斜线