Linux 同步读取log,一个同步日志系统的简单实现 log for c (linux 平台)

在一个项目中需要使用日志记录,网上也有很多开源代码,自己也尝试着写了一个!异步日志系统正在进行中。

//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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值