一个同步日志系统的简单实现 log for c (linux 平台)
2013-12-03 21:18
393 查看
在一个项目中需要使用日志记录,网上也有很多开源代码,自己也尝试着写了一个!异步日志系统正在进行中。
函数实现:
//mylog.h 头文件 #ifndef _MYLOG_HEADER_ #define _MYLOG_HEADER_ #ifdef __cpluscplus extern "C"{ #endif #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <sys/epoll.h> #include <sys/eventfd.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <time.h> #include <error.h> #define LOG_MAX_FILE_NAME (64) #define LOG_MAX_OUTPUT_NAME (128) #define LOG_TIME_STR_LEN (21) #define MAX_FILE_COUNT (50) #define MAX_FILE_SIZE (1024*1024*3) /**************** 每一个文件对于一个这样的结构体 ,不管是多线程写还是单线程 都是对应一个描述文件的结构体 ****************************/ typedef struct _log_file_t_ { FILE *fp; //文件指针 unsigned char filename[LOG_MAX_FILE_NAME];//输入文件的名字 unsigned char output_filename[LOG_MAX_OUTPUT_NAME];//输出文件的名字 unsigned int filesize;// 当前文件的大小 unsigned int active_count;//写文件的线程数 }log_file_t; typedef struct _log_t { pthread_key_t key; pthread_mutex_t mutex; unsigned int roll_size; unsigned int max_filesize; log_file_t *file_count[MAX_FILE_COUNT]; unsigned char last_time_str[LOG_TIME_STR_LEN+1]; unsigned int file_index; }f_log; char* _log_create_filename(char* filename,char* output_filename); #ifdef __cpluscplus } #endif #endif
函数实现:
#include "mylog.h" static f_log* g_log = NULL; static pthread_once_t init_create = PTHREAD_ONCE_INIT; /********************* 内部函数实现 ********************/ // 全局变量 初始化 static void _log_init() { int i; f_log *temp_glo=NULL; temp_glo = (f_log*)malloc(sizeof(f_log)); if(temp_glo == NULL) { printf("Can not malloc f_log!!!\r\n"); return ; } pthread_mutex_init(&temp_glo->mutex,NULL); temp_glo->max_filesize = MAX_FILE_SIZE; // 20MB temp_glo->file_index = 0; for(i=0;i<MAX_FILE_COUNT;i++) { temp_glo->file_count[i] == NULL; } g_log=temp_glo; } static inline int _lopen(const char* filename) { return open(filename,O_CREAT | O_WRONLY | O_APPEND,644); } static inline FILE* _log_open(const char* filename) { int fd= _lopen(filename); if(fd<0) { printf("Can not open file !\r\n"); return NULL; } FILE* f = fdopen(fd,"a"); if(f== NULL) { printf("Can open not \r\n"); return NULL; } return f; } // 写封装 static int _log_write_unlocked(log_file_t *f,char* log,int len) { int remain_len,write_len,temp; remain_len = len; write_len = 0; while(remain_len) { temp=fwrite(log,1,len,f->fp); write_len+=temp; // printf("fddfdfdffd\r\n"); remain_len-=temp; } return write_len; } static void _log_roll_file(log_file_t* f) { fclose(f->fp); _log_create_filename(f->filename,f->output_filename); f->fp = _log_open(f->output_filename); f->filesize = 0; // snprintf(f->filename,LOG_MAX_FILE_NAME,"%s",filename); } // 写日志 static int _log_write(log_file_t *f,char* log,int len) { int write_len=0; if(!f || !log ) { return 0; } write_len=_log_write_unlocked(f,log,len); if(write_len < len) { printf("Can not write log to f!\r\n"); return 0; } fflush(f->fp); f->filesize +=write_len; if(f->filesize > g_log->max_filesize) { _log_roll_file(f); } return write_len; } char* _log_create_filename(char* filename,char* output_filename) { char now_time[22]; time_t tm_time = time(NULL); struct tm now; gmtime_r(&tm_time,&now); snprintf(now_time,22,"%04d_%02d_%02d_%02d_%02d_%02d",(now.tm_year+1900),now.tm_mon+1,now.tm_mday,now.tm_hour,now.tm_min,now.tm_sec); snprintf(output_filename,LOG_MAX_OUTPUT_NAME,"%s_%s.txt",filename,now_time); return output_filename; } static void _log_get_time(time_t tm_time,char* time_str) { struct tm now; gmtime_r(&tm_time,&now); snprintf(time_str,LOG_TIME_STR_LEN+1,"[%04d_%02d_%02d %02d:%02d:%02d]",(now.tm_year+1900),now.tm_mon+1,now.tm_mday,now.tm_hour,now.tm_min,now.tm_sec); } static int _log_get_file_sig(char* file_sig,int file_sig_len,char* output_file_sig) { if(!file_sig) { return 0; } snprintf(output_file_sig,file_sig_len+3,"[%s]",file_sig); // printf("output file sig is %s\r\n",output_file_sig); return 1; } static inline int _log_get_sync_head(char* buf,char* file_sig,int file_sig_len) { time_t tm_check = time(NULL); char sig_buf[file_sig_len+2]; if( !buf) { return 0; } pthread_mutex_lock(&g_log->mutex); _log_get_time(tm_check,g_log->last_time_str); _log_get_file_sig(file_sig,file_sig_len,sig_buf); pthread_mutex_unlock(&g_log->mutex); strncpy(buf,g_log->last_time_str,LOG_TIME_STR_LEN); if(!file_sig) { file_sig_len = 0; } else { strncpy(buf+LOG_TIME_STR_LEN,sig_buf,file_sig_len+2); } return LOG_TIME_STR_LEN+file_sig_len+2; } // 写日志 在封装 是否达到文件的最大值 static int _log_sync_write(log_file_t *f,char* file_sig,int file_sig_len,char* log,int len) { int write_len,head_len; write_len =0; char buf[LOG_TIME_STR_LEN+file_sig_len+2+1]; head_len = _log_get_sync_head(buf,file_sig,file_sig_len); pthread_mutex_lock(&g_log->mutex); write_len += _log_write(f,buf,head_len); // write_len += _log_write(f,file_sig,file_sig_len); write_len += _log_write(f,log,len); write_len += _log_write(f,"\n",1); // printf("write_len is %d\r\n",write_len); pthread_mutex_unlock(&g_log->mutex); return 1; } void find_file(f_log *g_log,char* filename,log_file_t** created_file) { int i; *created_file == NULL; for(i=0;i<g_log->file_index;i++) { if(!strcmp(filename,g_log->file_count[i]->filename)) { *created_file=g_log->file_count[i]; } } } /************************** 外部函数 接口 **************************/ // 初始化描述文件的结构体 log_file_t* log_create(char* filename) { pthread_once(&init_create,_log_init); log_file_t *f=NULL; pthread_mutex_lock(&g_log->mutex); { find_file(g_log,filename,&f); if(f) { f->active_count++; pthread_mutex_unlock(&g_log->mutex); return f; } f = malloc(sizeof(log_file_t)); if(!f) { printf("Can not malloc f!\r\n"); pthread_mutex_unlock(&g_log->mutex); return NULL; } _log_create_filename(filename,f->output_filename); f->fp = _log_open(f->output_filename); f->filesize = 0; snprintf(f->filename,LOG_MAX_FILE_NAME,"%s",filename); g_log->file_count[g_log->file_index]=f; g_log->file_index++; f->active_count = 1; } pthread_mutex_unlock(&g_log->mutex); return f; } // 阻塞写 & 非阻塞写 int log_file_write(log_file_t* f,char* file_sig,int file_sig_len,char* log,int len) { if(!f || !log) { printf("F is null!\r\n"); return 0; } _log_sync_write(f,file_sig,file_sig_len,log,len); // _log_async_write(f,file_sig,file_sig_len,log,len); return 0; }自己的测试 程序:
#include "mylog.h" typedef struct _log_info_ { unsigned char name[16]; unsigned char file_sig[16]; unsigned char log[256]; unsigned int log_len; unsigned int file_sig_len; unsigned int i; }log_info; void *thread_func(void* argc) { log_info *file_info=(log_info*)argc; log_file_t * f=NULL; f=log_create(file_info->name); // log_set_mode(1); int i; for(i=0;i<500000;i++) log_file_write(f,file_info->file_sig,file_info->file_sig_len,file_info->log,file_info->log_len); } int main() { struct timeval start,end; log_info log_test; pthread_t pid[100]; memset(&log_test,0x00,sizeof(log_test)); strcpy(log_test.name,"aest"); strcpy(log_test.file_sig,"wang"); strcpy(log_test.log,"fdsajlkfjdsjlkfjdlsajfdlskfjlakdjflkdjsalfkjdslkfjdlakjflkdsjfjfdklstest"); // strcpy(log_test.log,"fdsajltest"); log_test.log_len=strlen(log_test.log); log_test.file_sig_len = strlen(log_test.file_sig); log_file_t *f=NULL; int i,ret; f=log_create(log_test.name); memset(&start,0x00,sizeof(start)); memset(&end,0x00,sizeof(end)); #if 1 gettimeofday(&start,NULL); for(i=0;i<900000;i++) { if(i%1000 == 0) { printf("a\r\n"); // f=log_create(log_test.name); } log_file_write(f,log_test.file_sig,log_test.file_sig_len,log_test.log,log_test.log_len); } gettimeofday(&end,NULL); printf("time is %d\r\n",(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec)); #endif #if 0 gettimeofday(&start,NULL); for(i=0;i<3;i++) { // log_test.i=i; // printf("i is %d\n",i); ret=pthread_create(&pid[i],NULL,thread_func,(void*)&log_test); pthread_join(pid[i],NULL); if(ret!=0) printf("can not create!\n"); usleep(100); } sleep(10); gettimeofday(&end,NULL); printf("time is %d\r\n",(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec)); #endif return 0; }
相关文章推荐
- 在i386平台Linux 2.6 上实现一个系统调用
- 教你如何实现windows与linux跨系统平台的一种简单的共享!!
- Linux下一个简单的日志系统的设计及其C代码实现
- 使用Node.js + MongoDB实现一个简单的日志分析系统
- 使用Node.js + MongoDB实现一个简单的日志分析系统
- Linux下一个简单的日志系统的设计及其C代码实现
- 基于C#中的Trace实现一个简单的日志系统
- Linux下一个简单的日志系统的设计及其C代码实现
- 树莓派开发板--Linux系统--ROS环境--实现一个简单的消息发布器和订阅器
- Linux下一个简单的日志系统的设计及其C代码实现
- 使用Node.js + MongoDB实现一个简单的日志分析系统
- linux平台下C语言实现一个简单的httpsever
- 在i386平台Linux 2.6 上实现一个系统调用
- 【1】实现一个简单的linux系统引导程序
- 在linux下实现简单聊天系统(三)服务器
- Linux系统编程_1_目录读取(实现简单ls命令)
- Linux脚本设计练习2——一个游戏菜单的简单实现
- Linux中实现一个简单的进度条
- Linux平台用C++实现信号量,同步线程
- 基于JAVA集合框架实现一个简单的学生管理系统