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

原创 2013年12月03日 21:18:57

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

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

}



版权声明:

相关文章推荐

TCP/IP详解--滑动窗口与内核缓冲区之间的关系

在有关TCP连接的很多配置中,有很多选项有的配置 net.ipv4.tcp_rmem:这个参数定义了TCP接收缓冲(用于TCP接收滑动窗口)的最小值、默认值、最大值 net.ipv4.tcp_wme...

数据包接受完整流程

TCP/IP数据包的完整接收流程! 入口自然是从driver开始,以Intel(R) PRO/1000 Network Driver对应的e1000_main.c为例。 事先声明,因为本人...

糊涂窗口综合症和Nagle算法

TCP/IP详解系列,关于tcp拥塞控制和数据流的地方讲的不细致,或许是涉及概念/算法太多,作者略去了一些对初学者来说比较陌生的细节吧。比如SWS未说明是什么就开始介绍其避免方法,还和nagle扯在了...

TCP/IP详解--TCP/IP连接各个状态转换分析

一、Linux服务器上11种网络连接状态:       图:TCP的状态机 通常情况下,一个正常的TCP连接,都会有三个阶段:1、TCP三次握手; 2、数据传送; 3、TCP四次挥手 注:以下说明...

TCP/IP详解--ICMP报文分析

一.概述: 1.   ICMP允许主机或路由报告差错情况和提供有关异常情况。ICMP是因特网的标准协议,但ICMP不是高层协议,而是IP层的协议。通常ICMP报文被IP层或更高层协议(TCP或UDP)...

TCP/IP详解--影响TCP性能的几种协议因素

影响TCP性能的协议因素: (1)TCP连接建立握手 (2)TCP慢启动拥塞控制; (3)数据聚集的Nagle算法; (4)用于捎带确认的TCP延迟确认机制。 (5)TIME_WAIT时延和端口耗尽。...

详解KMP算法

KMP算法应该是每一本《数据结构》书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么一回事,但...

TCP/IP模型背后的内涵(二)

1.TCP/IP模型与OSI模型 TCP/IP模型从一开始就是从实践走出来的,因此它能更好地迎合实际的应用而不单单停留在纸面上。从TCP/IP的发展史来看,它将IP从TCP独立出来的一部分原因是旨在...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)