在Linux环境下开发后台服务或高并发程序时,一个稳定、高效的日志系统是必不可少的调试和监控工具。本文将从零开始,手把手带你实现一个可用的Linux日志库,支持多线程安全、日志分级、异步写入等特性,全程使用C语言实现,并融入多线程日志设计思想。即使你是Linux编程新手,也能通过本教程掌握日志系统的核心原理。
现成的日志库(如log4c、syslog)虽然功能丰富,但往往过于臃肿或定制性差。手搓一个轻量级日志系统不仅能让你深入理解底层I/O、线程同步等知识,还能根据项目需求灵活裁剪。我们的目标是实现一个简单但完整的日志库,支持:
我们采用生产者-消费者模型:业务线程产生日志消息,放入缓冲区;后台线程负责将缓冲区数据写入磁盘。关键数据结构如下:
typedef enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR } log_level_t;typedef struct log_msg { log_level_t level; char content[MAX_LOG_LEN]; struct timeval tv;} log_msg_t;typedef struct log_queue { log_msg_t *buffer; int size; int in, out; pthread_mutex_t mutex; pthread_cond_t not_full, not_empty; int stop;} log_queue_t; 接口设计尽量简洁:log_init()、log_write()、log_flush()、log_close()。
使用pthread_mutex_t保护环形缓冲区的读写,用pthread_cond_t实现生产者和消费者的同步。当缓冲区满时,生产者等待;缓冲区空时,消费者等待。以下为写入日志的核心代码:
void log_write(log_level_t level, const char *fmt, ...) { if (queue.stop) return; pthread_mutex_lock(&queue.mutex); while ((queue.in + 1) % queue.size == queue.out) { pthread_cond_wait(&queue.not_full, &queue.mutex); } log_msg_t *msg = &queue.buffer[queue.in]; msg->level = level; gettimeofday(&msg->tv, NULL); va_list args; va_start(args, fmt); vsnprintf(msg->content, MAX_LOG_LEN, fmt, args); va_end(args); queue.in = (queue.in + 1) % queue.size; pthread_cond_signal(&queue.not_empty); pthread_mutex_unlock(&queue.mutex);} 后台线程不断从缓冲区取出消息,并写入文件。这里使用fwrite批量写入以提高性能,同时每秒或缓冲区满时主动刷新。
void *log_worker(void *arg) { FILE *fp = fopen(LOG_FILE, "a"); if (!fp) return NULL; while (1) { pthread_mutex_lock(&queue.mutex); while (queue.in == queue.out && !queue.stop) { pthread_cond_wait(&queue.not_empty, &queue.mutex); } if (queue.stop && queue.in == queue.out) { pthread_mutex_unlock(&queue.mutex); break; } log_msg_t *msg = &queue.buffer[queue.out]; queue.out = (queue.out + 1) % queue.size; pthread_cond_signal(&queue.not_full); pthread_mutex_unlock(&queue.mutex); // 写入文件 fprintf(fp, "[%ld.%06ld] [%s] %s", msg->tv.tv_sec, msg->tv.tv_usec, level_str(msg->level), msg->content); fflush(fp); // 可选,根据性能调整 } fclose(fp); return NULL;} 将上述模块整合成logger.h和logger.c,并提供以下示例:
#include "logger.h"int main() { log_init(1024); // 缓冲区大小 log_write(LOG_INFO, "Server started, pid=%d", getpid()); // 模拟多线程写日志 // ... log_flush(); log_close(); return 0;} 在Linux下编译(需链接pthread):gcc -o test test.c logger.c -lpthread。通过压测观察CPU和磁盘I/O,可调整缓冲区大小、刷新策略等。一个优秀的Linux日志库应当在高并发下依然稳定。
本文从零实现了多线程日志的核心功能。你可以在此基础上增加日志文件滚动、配置文件支持、网络发送等特性。通过手搓日志系统,你不仅掌握了一个实用工具,更深入理解了Linux系统编程的精髓。现在就去试试吧!
关键词:日志系统、Linux日志库、C语言日志实现、多线程日志
本文由主机测评网于2026-02-25发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20260227093.html