linux下c语言简单实现写日志函数(多线程安全)

Posted Hero_HL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux下c语言简单实现写日志函数(多线程安全)相关的知识,希望对你有一定的参考价值。

调用时包含hhl_log.h文件后使用宏替代函数进行写入日志操作

// eg:
FATAL("a:%d b:%s",  a, b);
ALERT("a:%d b:%s",  a, b);
CRITICAL("a:%d b:%s",  a, b);
ERROR("a:%d b:%s",  a, b);
WARNING("a:%d b:%s",  a, b);
NOTICE("a:%d b:%s",  a, b);
INFO("a:%d b:%s",  a, b);
DEBUG("a:%d b:%s",  a, b);


//CheckErrorReturn等价为 
//if( (a == 1) )
//
//	ERROR("a is 1, return 0 msg:%s\\n", msg);
//	return 0;
//
CheckErrorReturn(a == 1, 0, "a is 1, return 0 msg:%s\\n", msg);

write_log.h

#ifndef __WRITE_LOG_H__
#define __WRITE_LOG_H__
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h> 
#include <unistd.h> 
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>
#include <sys/syscall.h>//Linux system call for thread id

/* exps is true, return ret */
#define CheckErrorReturn(exps, ret, msg, ...)       \\
do                                                  \\
                                                   \\
    if ((exps))                                     \\
                                                   \\
        ERROR(msg, ##__VA_ARGS__);                  \\
        return (ret);                               \\
                                                   \\
                                                   \\
while(0)                                            \\

/* exps is true, return */
#define CheckErrorReturnVoid(exps, msg, ...)        \\
do                                                  \\
                                                   \\
    if ((exps))                                     \\
                                                   \\
        ERROR(msg, ##__VA_ARGS__);                  \\
        return ;                                    \\
                                                   \\
                                                   \\
while(0)                                            \\

/* exps is true, goto label */
#define CheckErrorGoto(exps, label, msg, ...)       \\
do                                                  \\
                                                   \\
    if ((exps))                                     \\
                                                   \\
        ERROR(msg, ##__VA_ARGS__);                  \\
        goto label;                                 \\
                                                   \\
                                                   \\
while(0)                                            \\

/* system is unusable   */
#define FATAL(msg, ...)         PrintLog("Fatal", msg, ##__VA_ARGS__)
/* action must be taken immediately */
#define ALERT(msg, ...)         PrintLog("Alert", msg, ##__VA_ARGS__)
/* critical conditions */
#define CRITICAL(msg, ...)      PrintLog("Critical", msg, ##__VA_ARGS__)
/* error conditions */
#define ERROR(msg, ...)         PrintLog("Error", msg, ##__VA_ARGS__)
/* warning conditions */
#define WARNING(msg, ...)       PrintLog("Warning", msg, ##__VA_ARGS__)
/* normal but significant condition  */
#define NOTICE(msg, ...)        PrintLog("Notice", msg, ##__VA_ARGS__)
/* informational */
#define INFO(msg, ...)          PrintLog("Info", msg, ##__VA_ARGS__)
/* debug-level messages  */
#define DEBUG(msg, ...)         PrintLog("Debug", msg, ##__VA_ARGS__)

#define PrintLog(level_str, msg, ...) \\
do  \\
    printf("[%s][%s][%s][%d] "msg, level_str, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \\
    write_log("[%s][%s][%s][%d] "msg, level_str, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \\
 while (0)

void write_log(const char* format, ...);


#endif






write_log.c

// log.cpp: 定义应用程序的入口点。
//

#include "write_log.h"
static pthread_mutex_t fileMutex = PTHREAD_MUTEX_INITIALIZER;

int safe_check_vasprintf(char** strp, const char* fmt, va_list ap)

	int retval;

	retval = vasprintf(strp, fmt, ap);
	if (retval == -1)
	
		printf("Failed to vasprintf: %s. Bailing out\\n", strerror(errno));
		return 1;
	
	return retval;


int safe_asprintf(char** strp, const char* fmt, ...)

	va_list ap;
	int retval;

	va_start(ap, fmt);
	retval = safe_check_vasprintf(strp, fmt, ap);
	va_end(ap);

	return retval;


void write_log(const char* format, ...)

    pthread_mutex_lock(&fileMutex);

    FILE* fp = NULL;
    va_list vlist;
    char* fmt = NULL;

    // Open debug info output file.
    if (!(fp = fopen("log.txt", "a+")))
    
        pthread_mutex_unlock(&fileMutex);
        return;
    

    va_start(vlist, format);
    safe_check_vasprintf(&fmt, format, vlist);
    va_end(vlist);
    if (!fmt)
    
        pthread_mutex_unlock(&fileMutex);
        return;
    

    time_t timep;
    struct tm* ptm = NULL;
    time(&timep);
    ptm = localtime(&timep);
    fprintf(fp, "[%04d-%02d-%02d-%02d:%02d:%02d][pid:%ld]%s",
        ptm->tm_year + 1900,
        ptm->tm_mon + 1,
        ptm->tm_mday,
        ptm->tm_hour,
        ptm->tm_min,
        ptm->tm_sec,
        syscall(SYS_gettid),
        fmt);

    free(fmt);
    fsync(fileno(fp));
    fclose(fp);

    pthread_mutex_unlock(&fileMutex);




以上是关于linux下c语言简单实现写日志函数(多线程安全)的主要内容,如果未能解决你的问题,请参考以下文章

windows环境下c语言支持ftp和http多线程下载的客户端

C语言怎么写线程代码

C语言中 怎么实现双线程 或者 父子线程啊

linux系统下,c语言pthread多线程编程传参问题

用C语言如何实现多线程同时运行的情况下,各个线程输出不同的随机数?

linux下c语言实现多线程文件复制