在一个项目中需要使用日志记录,网上也有很多开源代码,自己也尝试着写了一个!异步日志系统正在进行中。
//mylog.h 头文件
#ifndef _MYLOG_HEADER_
#define _MYLOG_HEADER_
#ifdef __cpluscplus
extern "C"{
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
{
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;ifile_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;
}