• Clog——基于C语言的日志系统设计


    clog——一种基于Linux C的日志系统

    在linux环境下使用c语言开发的一款日志系统clog,统一接口,功能丰富。

    支持的功能

    • 支持多线程日志采集。
    • 支持多进程日志采集,多进程采用tcp、udp或共享内存通信。
    • 支持自定义日志格式。
    • 支持多方式日志输出,file、console。

    代码结构

    ├── config.h             #clog的配置头文件,通过宏定义,用户可以自定义自己的clog日志系统
    ├── clog.h               #clog头文件,定义clog日志系统的接口
    	├── clog.c           #clog日志内容组合
    	├── consoleclog.c    #clog日志终端输出
    	├── fileclog.c       #clog日志文件输出
    	├── shmclog.c        #clog日志多进程共享内存输出日志
    	├── tcpclog.c        #clog日志多进程tcp输出日志
    		├── tcp.c
    		├── tcp.h
    	└── udpclog.c        #clog日志多进程udp输出日志
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    日志级别

    支持5种日志级别,errorwarninginfodebugtrace

    //日志级别
    typedef enum
    {
        CLOG_ERROR=0,
        CLOG_WARNING=1,
        CLOG_INFO=2,
        CLOG_DEBUG=3,
        CLOG_TRACE=4
    }Clog_Print_Level;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    日志内容

    【日志级别】-【时间】-【模块名】-【组件名】-【进程id】-【线程id】-【文件名】-【行号】-【函数名】->日志内容

    [ERROR]-[2216-11-13 21:36:20.837]-[clog]-[clog]-[5624]-[140016484947776]-[main.c]-[23]-[random_gen_log]-> HJIGJHF
    [WARN]-[2216-11-13 21:36:20.837]-[clog]-[clog]-[5624]-[140016484947776]-[main.c]-[24]-[random_gen_log]-> HJIGJHF
    [INFO]-[2216-11-13 21:36:20.837]-[clog]-[clog]-[5624]-[140016484947776]-[main.c]-[25]-[random_gen_log]-> HJIGJHF
    [DEBUG]-[2216-11-13 21:36:20.837]-[clog]-[clog]-[5624]-[140016484947776]-[main.c]-[26]-[random_gen_log]-> HJIGJHF
    [TRACE]-[2216-11-13 21:36:20.837]-[clog]-[clog]-[5624]-[140016484947776]-[main.c]-[27]-[random_gen_log]-> HJIGJHF
    
    • 1
    • 2
    • 3
    • 4
    • 5

    用户可以根据自己的需求自定义日志内容

    //日志打印内容
    #define CONTAIN_LOG_LEVEL              1  //是否显示日志级别   1->显示,0->不显示
    #define CONTAIN_LOG_TIME               1  //是否显示日志时间   1->显示,0->不显示  
    #define CONTAIN_LOG_MODULE             1  //是否显示日志模块名 1->显示,0->不显示
    #define CONTAIN_LOG_COMPONENT          1  //是否显示日志组件名 1->显示,0->不显示
    #define CONTAIN_LOG_FILENAME           1  //是否显示日志文件名 1->显示,0->不显示
    #define CONTAIN_LOG_LINENAME           1  //是否显示日志行号   1->显示,0->不显示
    #define CONTAIN_LOG_FUNCNAME           1  //是否显示日志函数名 1->显示,0->不显示
    #define CONTAIN_LOG_PROCESSID          1  //是否显示日志进程id 1->显示,0->不显示
    #define CONTAIN_LOG_THREADID           1  //是否显示日志线程id 1->显示,0->不显示
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    日志输出方式

    日志支持输出到文件和终端,通过宏定义供用户选择输出方式

    #define SUPPORT_CLOG_FILE                1  //0-->关闭输出到文件 1-->开启输出到文件
    #define SUPPORT_CLOG_CONSOLE             1  //0->关闭输出到终端 1-->开启输出到终端
    
    #define SUPPORT_MULTI_PROCESS            1  //0-->单进程 1-->多进程
    #define DATA_TRANSFER_WAY                0  //0-->使用共享内存作为数据传递 1-->使用tcp作为数据传递 2-->使用UDP作为数据传递
    
    • 1
    • 2
    • 3
    • 4
    • 5

    多进程下,用户可以选择进程间的通信方式,tcp、udp、共享内存。用以进行日志的输出

    每一种通信方式下,只有一个server端和多个client端server端通过通信方式接收其他进程的日志内容,并将日志内容输入到文件或终端。client端为日志生产者,通过多进程通信方式不断的向server端发送日志内容

    日志接口定义

    日志内容输出接口,采用c语言的变参函数设计,支持任意长度的日志内容

    clog_e(...)  // error级别
    clog_w(...)  // warning级别
    clog_i(...)  // info级别
    clog_d(...)  // debug级别
    clog_t(...)  // trace级别
    
    • 1
    • 2
    • 3
    • 4
    • 5
    日志文件
    //设置日志文件存储目录
    int set_log_file_save_dir(const char* logdir);
    //设置文件日志存储的最小日志级别
    void set_log_file_level(Clog_Print_Level plevel);
    
    • 1
    • 2
    • 3
    • 4
    日志终端
    //设置终端日志打印的最小日志级别
    void set_log_console_level(Clog_Print_Level plevel);
    //设置终端日志每个日志级别,打印的文字颜色
    void set_console_level_color(Clog_Print_Level plevel,Clog_Console_FG_Color fg_color);
    //console 终端打印字体颜色
    typedef enum
    {
        FG_DEFAULT=0,
        FG_Black=30,
        FG_Red=31,
        FG_Green=32,
        FG_Yellow=33,
        FG_Blue =34,
        FG_Magenta=35,
        FG_Cyan=36,
        FG_White=37
    }Clog_Console_FG_Color;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    日志TCP
    //设置tcp client连接时用到的ip地址和端口号,使client端建立tcp连接
    int log_tcp_connect(const char ip[16],unsigned short tcp_port);
    //设置tcp server端的端口号,可用于接收client端socket连接的子线程数量
    int log_tcp_server(unsigned short tcp_port,unsigned int thread_count);
    
    • 1
    • 2
    • 3
    • 4
    日志UDP
    //设置udp client端连接时用到的ip地址和端口号
    int log_set_udp(const char ip[16],unsigned short udp_port);
    //设置udp server端的IP地址和端口号
    int log_udp_server(const char ip[16],unsigned short udp_port);
    
    • 1
    • 2
    • 3
    • 4
    日志共享内存
    //共享内存server端
    int log_shm_server();
    //共享内存client端
    int log_shm_connect();
    
    • 1
    • 2
    • 3
    • 4

    使用demo

    #include 
    #include 
    #include 
    
    #include 
    
    #include "clog.h"
    
    //随机生成指定条数和指定大小的日志内容
    #define LOG_COUNT   50
    #define LOG_SIZE    20
    void random_gen_log()
    {
        int index=0;
        for(index=0;index<LOG_COUNT;index++)
        {
            //随机数产生日志单条内容长度
            int log_len=5+rand()%(LOG_SIZE);
            char* log_data=(char*)malloc(log_len* sizeof(char));
            int index=0;
            for(index=0;index<log_len-1;index++)
            {
                log_data[index]='A'+rand()%26;
            }
            log_data[index]='\0';
    
            clog_e("%s",log_data);
            clog_w("%s",log_data);
            clog_i("%s",log_data);
            clog_d("%s",log_data);
            clog_t("%s",log_data);
    
            free(log_data);
            log_data=NULL;
            usleep(1000*10);
        }
    }
    
    //测试单进程下的文件和终端日志
    void test_clog_file_console()
    {
        set_log_console_level(CLOG_TRACE);
        set_console_level_color(CLOG_ERROR,FG_Red);
        set_console_level_color(CLOG_WARNING,FG_Yellow);
        set_console_level_color(CLOG_INFO,FG_DEFAULT);
        set_console_level_color(CLOG_DEBUG,FG_Blue);
        set_console_level_color(CLOG_TRACE,FG_Cyan);
    
        set_log_file_save_dir("/home/nvidia/Videos/");
        set_log_file_level(CLOG_TRACE);
    
        random_gen_log();
    }
    
    //测试多进程下的使用tcp传输日志
    void test_clog_tcp(int argc,char* argv[])
    {
        if(argc!=2)
        {
            return;
        }
    
        if(strcmp(argv[1],"client")==0)
        {
            log_tcp_connect("127.0.0.1",7789);
            random_gen_log();
        }
        else if(strcmp(argv[1],"server")==0)
        {
            set_log_console_level(CLOG_TRACE);
            set_console_level_color(CLOG_ERROR,FG_Red);
            set_console_level_color(CLOG_WARNING,FG_Yellow);
            set_console_level_color(CLOG_INFO,FG_DEFAULT);
            set_console_level_color(CLOG_DEBUG,FG_Blue);
            set_console_level_color(CLOG_TRACE,FG_Cyan);
    
            set_log_file_save_dir("/home/nvidia/Videos/");
            set_log_file_level(CLOG_TRACE);
            log_tcp_server(7789,1);
        }
    }
    
    
    //测试多进程下的使用udp传输日志
    void test_clog_udp(int argc,char* argv[])
    {
        if(argc!=2)
        {
            return;
        }
    
        if(strcmp(argv[1],"client")==0)
        {
            log_set_udp("127.0.0.1",7789);
    
            random_gen_log();
        }
        else if(strcmp(argv[1],"server")==0)
        {
            set_log_console_level(CLOG_TRACE);
            set_console_level_color(CLOG_ERROR,FG_Red);
            set_console_level_color(CLOG_WARNING,FG_Yellow);
            set_console_level_color(CLOG_INFO,FG_DEFAULT);
            set_console_level_color(CLOG_DEBUG,FG_Blue);
            set_console_level_color(CLOG_TRACE,FG_Cyan);
    
            set_log_file_save_dir("/home/nvidia/Videos/");
            set_log_file_level(CLOG_TRACE);
            log_udp_server("127.0.0.1",7789);
        }
    }
    
    //测试多进程下的使用共享内存传输日志
    void test_clog_shm(int argc,char* argv[])
    {
        if(argc!=2)
        {
            return;
        }
    
        if(strcmp(argv[1],"client")==0)
        {
            log_shm_connect();
            random_gen_log();
        }
        else if(strcmp(argv[1],"server")==0)
        {
            set_log_console_level(CLOG_TRACE);
            set_console_level_color(CLOG_ERROR,FG_Red);
            set_console_level_color(CLOG_WARNING,FG_Yellow);
            set_console_level_color(CLOG_INFO,FG_DEFAULT);
            set_console_level_color(CLOG_DEBUG,FG_Blue);
            set_console_level_color(CLOG_TRACE,FG_Cyan);
    
            set_log_file_save_dir("/home/nvidia/Videos/");
            set_log_file_level(CLOG_TRACE);
            log_shm_server();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140

    源代码

    config.h

    #ifndef CLOG_CONFIG_H
    #define CLOG_CONFIG_H
    
    //日志打印内容
    #define CONTAIN_LOG_LEVEL              1
    #define CONTAIN_LOG_TIME               1
    //模块名
    #define CONTAIN_LOG_MODULE             1
    //组件名
    #define CONTAIN_LOG_COMPONENT          1
    #define CONTAIN_LOG_FILENAME           1
    #define CONTAIN_LOG_LINENAME           1
    #define CONTAIN_LOG_FUNCNAME           1
    //进程id
    #define CONTAIN_LOG_PROCESSID          1
    //线程id
    #define CONTAIN_LOG_THREADID           1
    
    #ifndef CLOG_MODULE_NAME
    #define CLOG_MODULE_NAME                 "clog"
    #endif
    
    #ifndef CLOG_COMPONENT_NAME
    #define CLOG_COMPONENT_NAME              "clog"
    #endif
    
    
    #define SUPPORT_CLOG_FILE                1 //0-->关闭输出到文件 1-->开启输出到文件
    #define SUPPORT_CLOG_CONSOLE             1 //0->关闭输出到终端 1-->开启输出到终端
    
    //单个文件最大大小
    #define CLOG_FILE_MAX_SIZE               (10*1024*1024)   //100M
    
    #define SUPPORT_MULTI_PROCESS            1 //0-->单进程 1-->多进程
    #define DATA_TRANSFER_WAY                0  //0-->使用共享内存作为数据传递 1-->使用tcp作为数据传递 2-->使用UDP作为数据传递
    
    #define CLOG_UDP_LENGTH                  1024
    
    #define CLOG_SHM_QUEUE_COUNT             5 //共享内存存储队列元素个数
    #define CLOG_SHM_QUEUE_LEN               1024 //共享内存单条日志最大size
    
    #endif //CLOG_CONFIG_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    clog.h

    #ifndef CLOG_CLOG_H
    #define CLOG_CLOG_H
    
    #include "config.h"
    
    #include 
    #include 
    
    //解决__FILE__为绝对路径的问题
    #define CLOG_FILENAME(x) (strrchr((x),'/')?strrchr((x),'/')+1:(x))
    
    //日志级别
    typedef enum
    {
        CLOG_ERROR=0,
        CLOG_WARNING=1,
        CLOG_INFO=2,
        CLOG_DEBUG=3,
        CLOG_TRACE=4
    }Clog_Print_Level;
    
    //console 终端打印字体颜色
    typedef enum
    {
        FG_DEFAULT=0,
        FG_Black=30,
        FG_Red=31,
        FG_Green=32,
        FG_Yellow=33,
        FG_Blue =34,
        FG_Magenta=35,
        FG_Cyan=36,
        FG_White=37
    }Clog_Console_FG_Color;
    
    #define clog_e(...)     clog_print(CLOG_ERROR,CLOG_MODULE_NAME,CLOG_COMPONENT_NAME,CLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__,__VA_ARGS__)
    #define clog_w(...)     clog_print(CLOG_WARNING,CLOG_MODULE_NAME,CLOG_COMPONENT_NAME,CLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__,__VA_ARGS__)
    #define clog_i(...)     clog_print(CLOG_INFO,CLOG_MODULE_NAME,CLOG_COMPONENT_NAME,CLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__,__VA_ARGS__)
    #define clog_d(...)     clog_print(CLOG_DEBUG,CLOG_MODULE_NAME,CLOG_COMPONENT_NAME,CLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__,__VA_ARGS__)
    #define clog_t(...)     clog_print(CLOG_TRACE,CLOG_MODULE_NAME,CLOG_COMPONENT_NAME,CLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__,__VA_ARGS__)
    
    void clog_print(Clog_Print_Level plevel,const char* module_name,const char* component_name,const char* filename,const int linenum,const char* funcname,char *fmt, ...);
    
    
    #if SUPPORT_CLOG_CONSOLE
    void set_log_console_level(Clog_Print_Level plevel);
    void set_console_level_color(Clog_Print_Level plevel,Clog_Console_FG_Color fg_color);
    void log_output_console(const char* clog_data);
    #endif
    
    #if SUPPORT_CLOG_FILE
    int set_log_file_save_dir(const char* logdir);
    void set_log_file_level(Clog_Print_Level plevel);
    void log_output_file(const char* clog_data);
    #endif
    
    #if SUPPORT_MULTI_PROCESS
    #if DATA_TRANSFER_WAY == 1
    int log_tcp_connect(const char ip[16],unsigned short tcp_port);
    int log_tcp_server(unsigned short tcp_port,unsigned int thread_count);
    void log_output_tcp(const char* clog_data);
    #elif DATA_TRANSFER_WAY == 2
    int log_set_udp(const char ip[16],unsigned short udp_port);
    int log_udp_server(const char ip[16],unsigned short udp_port);
    void log_output_udp(const char* clog_data);
    #elif DATA_TRANSFER_WAY == 0
    int log_shm_server();
    int log_shm_connect();
    int log_output_shm(const char* clog_data);
    #endif
    #endif
    
    #endif //CLOG_CLOG_H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    clog.c

    #include "clog.h"
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    //日志支持任意长度,默认时512字节,会根据日志的长度通过realloc函数动态调整
    static uint64_t clog_data_length=512;
    
    static char* level_to_char(Clog_Print_Level plevel)
    {
        switch (plevel)
        {
            case CLOG_ERROR:
                return "ERROR";
            case CLOG_WARNING:
                return "WARN";
            case CLOG_INFO:
                return "INFO";
            case CLOG_DEBUG:
                return "DEBUG";
            case CLOG_TRACE:
                return "TRACE";
        }
    }
    
    static void time_to_str(char timestr[24])
    {
        struct  tm      *ptm;
        struct  timeb   stTimeb;
    
        ftime(&stTimeb);
        ptm = localtime(&stTimeb.time);
        snprintf(timestr,24,"%04d-%02d-%02d %02d:%02d:%02d.%03d",
                                            ptm->tm_yday+1900,ptm->tm_mon+1, ptm->tm_mday,
                                            ptm->tm_hour, ptm->tm_min, ptm->tm_sec, stTimeb.millitm);
    }
    
    void clog_print(Clog_Print_Level plevel,const char* module_name,const char* component_name,const char* filename,const int linenum,const char* funcname,char *fmt, ...)
    {
        uint64_t ret=0;
        uint64_t total_len=0;
        uint64_t header_len=0;
    
        //total_length(uint64_t)+level(uint8_t)+log_data
        char *log_data=(char*)malloc(clog_data_length+2);
    
        char* log_ptr=log_data;
    
        char log_time[24]="\0";
        time_to_str(log_time);
    
        log_ptr+=sizeof(uint64_t);
    
        memcpy(log_ptr,&plevel,sizeof(uint8_t));
        log_ptr+=sizeof(uint8_t);
    
    #if CONTAIN_LOG_LEVEL
        log_ptr+=sprintf(log_ptr,"[%s]",level_to_char(plevel));
    #endif
    
    #if CONTAIN_LOG_TIME
        log_ptr+=sprintf(log_ptr,"-[%s]",log_time);
    #endif
    
    #if CONTAIN_LOG_MODULE
        log_ptr+=sprintf(log_ptr,"-[%s]",module_name);
    #endif
    
    #if CONTAIN_LOG_COMPONENT
        log_ptr+=sprintf(log_ptr,"-[%s]",component_name);
    #endif
    
    #if CONTAIN_LOG_PROCESSID
        log_ptr+=sprintf(log_ptr,"-[%u]",getpid());
    #endif
    
    #if CONTAIN_LOG_THREADID
        log_ptr+=sprintf(log_ptr,"-[%lu]",pthread_self());
    #endif
    
    #if CONTAIN_LOG_FILENAME
        log_ptr+=sprintf(log_ptr,"-[%s]",filename);
    #endif
    
    #if CONTAIN_LOG_LINENAME
        log_ptr+=sprintf(log_ptr,"-[%d]",linenum);
    #endif
    
    #if CONTAIN_LOG_FUNCNAME
        log_ptr+=sprintf(log_ptr,"-[%s]",funcname);
    #endif
    
        log_ptr+=sprintf(log_ptr,"-> ");
        header_len=(uint64_t)(log_ptr-log_data);
    
        va_list args;
        va_start(args, fmt);
        ret=vsnprintf(log_ptr,clog_data_length-header_len,fmt, args);
        va_end(args);
    
    	//根据日志的实际长度动态调整log_data的大小
        while((header_len+ret)>=clog_data_length)
        {
            clog_data_length+=clog_data_length;
            log_data=(char*)realloc(log_data, clog_data_length+2);
            log_ptr=log_data+header_len;
            va_list args;
            va_start(args, fmt);
            ret=vsnprintf(log_ptr,clog_data_length-header_len,fmt, args);
            va_end(args);
        }
    
        if(log_ptr[ret-1]!='\n')
        {
            log_ptr[ret]='\n';
            ret++;
        }
        log_ptr[ret]='\0';
        ret++;
        log_ptr+=ret;
    
    
        total_len=(uint64_t)(log_ptr-log_data);
        memcpy(log_data,&total_len,sizeof(uint64_t));
    
        //fprintf(stdout,"begin outptu device:%lu\n",total_len);
        //device output
    #if SUPPORT_MULTI_PROCESS
    #if DATA_TRANSFER_WAY == 1
        log_output_tcp(log_data);
    #elif DATA_TRANSFER_WAY == 2
        log_output_udp(log_data);
    #elif DATA_TRANSFER_WAY == 0
        log_output_shm(log_data);
    #endif
    #else
    #if SUPPORT_CLOG_FILE
            log_output_file(log_data);
    #endif
    
    #if SUPPORT_CLOG_CONSOLE
            log_output_console(log_data);
    #endif
    #endif
    
        free(log_data);
        log_data=NULL;
        return;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156

    consoleclog.c

    #include "clog.h"
    #include 
    #include 
    #include 
    
    static pthread_mutex_t log_console_mutex = PTHREAD_MUTEX_INITIALIZER;
    
    static Clog_Print_Level log_console_level=CLOG_INFO;
    static Clog_Console_FG_Color log_console_fg_color[5]={FG_DEFAULT,FG_DEFAULT,FG_DEFAULT,FG_DEFAULT,FG_DEFAULT};
    
    void set_log_console_level(Clog_Print_Level plevel)
    {
        log_console_level=plevel;
    }
    
    void set_console_level_color(Clog_Print_Level plevel,Clog_Console_FG_Color fg_color)
    {
        switch (plevel)
        {
            case CLOG_ERROR:
            {
                log_console_fg_color[0]=fg_color;
                break;
            }
            case CLOG_WARNING:
            {
                log_console_fg_color[1]=fg_color;
                break;
            }
            case CLOG_INFO:
            {
                log_console_fg_color[2]=fg_color;
                break;
            }
            case CLOG_DEBUG:
            {
                log_console_fg_color[3]=fg_color;
                break;
            }
            case CLOG_TRACE:
            {
                log_console_fg_color[4]=fg_color;
                break;
            }
        }
    }
    
    void log_output_console(const char* clog_data)
    {
        char* log_ptr=(char*)clog_data;
        uint64_t log_len=((uint64_t*)log_ptr)[0]-sizeof(uint64_t)-sizeof(uint8_t);
        log_ptr+=sizeof(uint64_t);
        Clog_Print_Level plevel=(Clog_Print_Level)(((uint8_t*)log_ptr)[0]);
        log_ptr+=sizeof(uint8_t);
        //fprintf(stdout,"console:total_len:%lu,plevel=%d\n",log_len,plevel);
    
        if(plevel<=log_console_level)
        {
            pthread_mutex_lock (&log_console_mutex);
            printf("\x1b[0;%dm%s\x1b[0m", (int)log_console_fg_color[(int)plevel], log_ptr);
            pthread_mutex_unlock (&log_console_mutex);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    fileclog.c

    #include "clog.h"
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    static pthread_mutex_t log_file_mutex = PTHREAD_MUTEX_INITIALIZER;
    static FILE* log_file_fp=NULL;
    static Clog_Print_Level log_file_level=CLOG_INFO;
    static int log_file_size=0;
    static int log_file_index=0;
    static char log_file_save_dir[128]="\0";
    
    int open_file()
    {
        char filename[256];
        time_t timep;
        struct tm *ptm;
        time(&timep);
        ptm = gmtime(&timep);
    
        sprintf(filename,"%s/clog_%04d-%02d-%02d_%d.log",log_file_save_dir,ptm->tm_year+1900,ptm->tm_mon+1, ptm->tm_mday,log_file_index);
        log_file_fp=fopen(filename,"w+");
        if(log_file_fp==NULL)
        {
            fprintf(stderr,"The log file failed to open:%s\n",filename);
            return -1;
        }
        log_file_size=0;
        return 0;
    }
    
    int set_log_file_save_dir(const char logdir[128])
    {
        //check is dir
        struct stat file_info;
        if (stat(logdir, &file_info) < 0)
        {
            fprintf(stderr,"get stat failed:%s\n",logdir);
            return -1;
        }
    
        if (S_ISDIR(file_info.st_mode)==0)
        {
            fprintf(stderr,"%s is not a dir\n",logdir);
            return -1;
        }
    
        if (access(logdir,W_OK | F_OK)<0)
        {
            fprintf(stderr,"The current user does not have write access to this directory:%s\n",logdir);
            return -1;
        }
    
        strncpy(log_file_save_dir,logdir, sizeof(log_file_save_dir));
    
        log_file_size=0;
        log_file_index=0;
    
        return open_file();
    }
    
    void set_log_file_level(Clog_Print_Level plevel)
    {
        log_file_level=plevel;
    }
    
    void log_output_file(const char* clog_data)
    {
        char* log_ptr=(char*)clog_data;
        uint64_t log_len=((uint64_t*)log_ptr)[0]-sizeof(uint64_t)-sizeof(uint8_t);
        log_ptr+=sizeof(uint64_t);
        Clog_Print_Level plevel=(Clog_Print_Level)(((uint8_t*)log_ptr)[0]);
        log_ptr+=sizeof(uint8_t);
        //fprintf(stdout,"file:total_len:%lu,plevel=%d\n",log_len,plevel);
    
        if(plevel<=log_file_level)
        {
            if(log_file_fp!=NULL)
            {
                pthread_mutex_lock (&log_file_mutex);
                log_file_size+=fwrite(log_ptr,log_len-1,1,log_file_fp);
                fflush(log_file_fp);
                if(log_file_size>=CLOG_FILE_MAX_SIZE)
                {
                    log_file_index++;
                    fclose(log_file_fp);
                    open_file();
                }
    
                pthread_mutex_unlock (&log_file_mutex);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    shmclog.c

    #include "clog.h"
    
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    key_t shm_key=1000;
    //无锁原子操作
    #define CAS(a_ptr, a_oldVal, a_newVal) __sync_bool_compare_and_swap(a_ptr, a_oldVal, a_newVal)
    
    //共享内存实现一读多写的无锁队列
    typedef struct
    {
        volatile int readindex;
        volatile int writeindex;
        char shm_log_data[CLOG_SHM_QUEUE_COUNT][1+CLOG_SHM_QUEUE_LEN];
    }SHM_CLOG_DATA;
    
    SHM_CLOG_DATA* shm_clog_data_ptr=NULL;
    
    int log_shm_server()
    {
        int shmid;
        void *shm_addr;
    
        // 创建共享内存
        if ((shmid = shmget(shm_key, sizeof(SHM_CLOG_DATA), 0666 | IPC_CREAT)) < 0)
        {
            fprintf(stderr,"shmget create shm memory failed:errno(%d)-%s\n",errno,strerror(errno));
            return -1;
        }
        fprintf(stdout,"shmget create shm memory successful\n");
    
        //映射共享内存
        if ((shm_addr = shmat(shmid, (void*)0, 0)) == (void*)-1)
        {
            fprintf(stderr,"shmat map shm memory failed:errno(%d)-%s\n",errno,strerror(errno));
            return -1;
        }
        fprintf(stdout,"shmat map shm memory successful\n");
    
        SHM_CLOG_DATA* shm_clog_data_ptr=(SHM_CLOG_DATA*)shm_addr;
    
        //init data
        shm_clog_data_ptr->readindex=0;
        shm_clog_data_ptr->writeindex=0;
        memset(shm_clog_data_ptr->shm_log_data,'\0',sizeof(shm_clog_data_ptr->shm_log_data));
    
        int currentMaximumReadIndex;
        int currentReadIndex;
        char* log_ptr=NULL;
    
        do{
            currentReadIndex = shm_clog_data_ptr->readindex;
            //fprintf(stdout,"currentReadIndex:%d\n",currentReadIndex);
    
            log_ptr=shm_clog_data_ptr->shm_log_data[currentReadIndex];
            while(!CAS(&(log_ptr[0]),1,0))
            {
                usleep(10*1000);//10ms
            }
    
            //begin write data to log
    #if SUPPORT_CLOG_FILE
            log_output_file(log_ptr+1);
    #endif
    
    #if SUPPORT_CLOG_CONSOLE
            log_output_console(log_ptr+1);
    #endif
            CAS(&(shm_clog_data_ptr->readindex), currentReadIndex, (currentReadIndex + 1)%CLOG_SHM_QUEUE_COUNT);
        }while(1);
    
        shmdt(shm_addr);
        return 0;
    }
    
    
    int log_shm_connect()
    {
        int shmid;
        char *shm_addr;
        // 创建共享内存
        if ((shmid = shmget(shm_key, sizeof(SHM_CLOG_DATA), 0)) < 0)
        {
            fprintf(stderr,"shmget create shm memory failed:errno(%d)-%s\n",errno,strerror(errno));
            return -1;
        }
    
        //映射共享内存
        if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1)
        {
            fprintf(stderr,"shmat map shm memory failed:errno(%d)-%s\n",errno,strerror(errno));
            return -1;
        }
    
        shm_clog_data_ptr=(SHM_CLOG_DATA*)shm_addr;
    
        return 0;
    }
    
    int log_output_shm(const char* clog_data)
    {
        uint64_t queue_max_len=CLOG_SHM_QUEUE_LEN;
        char* log_ptr=NULL;
        int currentWriteIndex;
        int currentReadIndex;
    
        do{
            currentWriteIndex=shm_clog_data_ptr->writeindex;
            currentReadIndex=shm_clog_data_ptr->readindex;
            if(((currentWriteIndex+1)%CLOG_SHM_QUEUE_COUNT) == (currentReadIndex%CLOG_SHM_QUEUE_COUNT))
            {
                //queue is full;
                usleep(10*1000);//10ms
                continue;
            }
        }while(!CAS(&(shm_clog_data_ptr->writeindex), currentWriteIndex, (currentWriteIndex+1)%CLOG_SHM_QUEUE_COUNT));
    
        //fprintf(stdout,"currentWriteIndex:%d\n",currentWriteIndex);
        log_ptr=shm_clog_data_ptr->shm_log_data[currentWriteIndex];
        memcpy((log_ptr+1),clog_data,queue_max_len);
        CAS(&(log_ptr[0]),0,1);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131

    udpclog.c

    #include "clog.h"
    
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    static int clog_udp_socket_fd=-1;
    struct sockaddr_in clog_udp_sock_addr;
    
    int log_set_udp(const char ip[16],unsigned short udp_port)
    {
        clog_udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
        memset(&clog_udp_sock_addr, 0, sizeof(clog_udp_sock_addr));
        clog_udp_sock_addr.sin_family = AF_INET;
        clog_udp_sock_addr.sin_port = htons(udp_port);
        clog_udp_sock_addr.sin_addr.s_addr = inet_addr(ip);
    }
    
    void log_output_udp(const char* clog_data)
    {
        if(clog_udp_socket_fd==-1)
        {
            return;
        }
    
        uint64_t total_len=((uint64_t*)clog_data)[0];
        sendto(clog_udp_socket_fd, clog_data, total_len, 0, (struct sockaddr*)&clog_udp_sock_addr, sizeof(clog_udp_sock_addr));
        return;
    }
    int log_udp_server(const char ip[16],unsigned short udp_port)
    {
        int udp_server_sockfd = socket(AF_INET,SOCK_DGRAM,0);
        fprintf(stdout,"create server socket ssuccessful\n");
    
        struct sockaddr_in saddr,caddr;
        memset(&saddr,0,sizeof(saddr));
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(udp_port);
        saddr.sin_addr.s_addr = inet_addr(ip);
    
        if(bind(udp_server_sockfd,(struct sockaddr*)&saddr,sizeof(saddr))!=0)
        {
            fprintf(stderr,"server bind failed:errno(%d)-%s\n",errno,strerror(errno));
            return -1;
        }
        fprintf(stdout,"server socket bind successful\n");
    
        unsigned int max_length=sizeof(uint64_t)+sizeof(uint8_t)+ sizeof(char)*CLOG_UDP_LENGTH;
    
        while(1)
        {
            int len = sizeof(caddr);
            char *log_data=(char*)malloc(max_length);
            recvfrom(udp_server_sockfd,log_data,max_length,0,(struct sockaddr*)&caddr,&len);
    
    #if SUPPORT_CLOG_FILE
            log_output_file(log_data);
    #endif
    
    #if SUPPORT_CLOG_CONSOLE
            log_output_console(log_data);
    #endif
        }
    
        close(udp_server_sockfd);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    tcpclog.c

    #include "clog.h"
    #include "tcp.h"
    
    static int clog_tcp_socket_fd=-1;
    int log_tcp_connect(const char ip[16],unsigned short tcp_port)
    {
        ///定义sockfd
        clog_tcp_socket_fd = socket(AF_INET,SOCK_STREAM, 0);
    
        ///定义sockaddr_in
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(tcp_port);  ///服务器端口
        servaddr.sin_addr.s_addr = inet_addr(ip);  ///服务器ip
    
        ///连接服务器,成功返回0,错误返回-1
        if (connect(clog_tcp_socket_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            fprintf(stderr,"connect clog tcp server(%s/%d) failed\n",ip,tcp_port);
            return -1;
        }
    
        return 0;
    }
    
    static int clog_tcp_handle(int socket_fd,void* arg)
    {
        uint64_t ret=0;
        uint64_t rd_len=0;
        uint64_t total_len;
        read(socket_fd,&total_len,sizeof(uint64_t));
        char *log_data=(char*)malloc(total_len*sizeof(char));
        *(uint64_t*)log_data=total_len;
        char *log_ptr=log_data+sizeof(uint64_t);
        total_len=total_len-sizeof(uint64_t);
    
        ret=0;
        rd_len=0;
        while(ret<total_len)
        {
            rd_len=read(socket_fd,log_ptr,(total_len-ret));
            log_ptr+=rd_len;
            ret+=rd_len;
        }
    
    #if SUPPORT_CLOG_FILE
        log_output_file(log_data);
    #endif
    
    #if SUPPORT_CLOG_CONSOLE
        log_output_console(log_data);
    #endif
    
        free(log_data);
        log_data=NULL;
    
        return 1;
    }
    
    int log_tcp_server(unsigned short tcp_port,unsigned int thread_count)
    {
        int result=0;
        server_struct *clog_server_info=initServerStruct(tcp_port,thread_count,clog_tcp_handle);
        result=serverRun(clog_server_info);
        free(clog_server_info);
        return result;
    }
    
    void log_output_tcp(const char* clog_data)
    {
        if(clog_tcp_socket_fd==-1)
        {
            return;
        }
    
        uint64_t total_len=((uint64_t*)clog_data)[0];
        write(clog_tcp_socket_fd,clog_data,total_len);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    tcp.c 和tcp.h 的具体实现 见

    基于epoll的多线程网络服务程序设计——C语言

  • 相关阅读:
    CppLib v1.1 和 pexports v4.7 的下载链接记录
    随机硬件地址?私有 WiFi 地址?随机 MAC 地址?
    如何入门编程?
    嵌入式启动细节
    C++ 函数模板
    接口测试常见问题
    Android笔记(二十三):以插件化APK方式启动带WebView的Activity
    【Unity】【VR】详解Oculus Integration输入
    oracle分区索引的理解和创建思路
    YOLOv6训练运行教程,鱼苗检测
  • 原文地址:https://blog.csdn.net/qq_33232152/article/details/127830298