logger.h
testlogger.c
#ifndef _LOGGER
#define _LOGGER
#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif
//#include <stdarg.h>
#define log sys_log
#define log_err(fmt,...) sys_log(1,fmt,## __VA_ARGS__)
//#define log_err(fmt,args...) sys_log(1,fmt,args)
void init_log(int level);
void release_log();
void sys_log(int,const char*,...);
struct sys_logger{
char* file_name;
char* file_path;
int fd[2];
FILE *stream[2];
};
#ifdef __cplusplus
}
#endif
#endif</stdarg></stdio>
logger.c
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include "logger.h"
static int log_level = 2;
struct sys_logger sys = {"sys","./log",{0,0},{NULL,NULL}};
void sys_log(int level,const char* fmt,...){
if(level > log_level)
return;//cancel the log ,return
va_list va;
va_start(va,fmt);//get variable parameters
time_t now;
time(&now);
struct tm *timenow = localtime(&now);
if(NULL == sys.stream[1]){
printf("Log FILE stream NULL");
char buf[4096]={0};//buffer
int bytes = snprintf(buf,sizeof buf,"%d-%02d-%02d %02d:%02d:%02d ",(1900+timenow->tm_year),(1+timenow->tm_mon),timenow->tm_mday,timenow->tm_hour,timenow->tm_min,timenow->tm_sec);
//format the content to the buffer
bytes += vsnprintf(buf + bytes,sizeof(buf) - bytes,fmt,va);
while(bytes > 0){
int wbytes = write(sys.fd[1],buf,strlen(buf));
//printf("write %d bytes,content:%s\n",wbytes,buf);
if(wbytes == -1 && errno != EAGAIN)
break;
bytes -= wbytes;
}
}else{
char fmt_buf[1024] ={0};
const char* const_fmt = fmt_buf;
sprintf(fmt_buf,"%d-%02d-%02d %02d:%02d:%02d %s",(1900+timenow->tm_year),(1+timenow->tm_mon),timenow->tm_mday,timenow->tm_hour,timenow->tm_min,timenow->tm_sec,fmt);
printf("%d",timenow->tm_year);
vfprintf(sys.stream[1],const_fmt,va);
}
va_end(va);
}
void get_log(void* fd){
FILE* fs = NULL;
time_t now;
time(&now);
struct tm *p = localtime(&now);
char file_name_buf[1024]={0};
//format the file name
snprintf(file_name_buf,1024
,sys.file_path[strlen(sys.file_path) - 1] == '/'?
"%s%d%02d%02d-%s":"%s/%d%02d%02d-%s"
,sys.file_path, (1900+p->tm_year),(1+p->tm_mon), p->tm_mday,sys.file_name);
if(mkdir(sys.file_path,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1 && errno != EEXIST){
printf("create log directory error.errno=%d.%s",errno,strerror(errno));
return ;
}
//Open for appending (writing at end of file). The file is
//created if it does not exist. The stream is positioned at
//the end of the file.
fs = fopen(file_name_buf,"a");
if(NULL == fs)
printf("log file %s open error.errno=%d,%s\n",file_name_buf,errno,strerror(errno));
else{
setvbuf(fs, (char *)NULL, _IOLBF, 0);
char new_file_name_buf[1024];
while(1){
memset(new_file_name_buf,0,sizeof new_file_name_buf);
time(&now);
p = localtime(&now);
//format the file name
snprintf(new_file_name_buf,1024
,sys.file_path[strlen(sys.file_path) - 1] == '/'?
"%s%d%02d%02d-%s":"%s/%d%02d%02d-%s"
,sys.file_path, (1900+p->tm_year),(1+p->tm_mon)
, p->tm_mday,sys.file_name);
if(strcmp(new_file_name_buf,file_name_buf) != 0){
fclose(fs);
fs = fopen(new_file_name_buf,"a");
if(NULL == fs){
printf("open new log file %s error.errno=%d,%s\n"
,new_file_name_buf,errno,strerror(errno));
break;
}
setvbuf(fs, (char *)NULL, _IOLBF, 0);
}else{
memset(file_name_buf,0,sizeof file_name_buf);//file
memcpy(file_name_buf,new_file_name_buf,strlen(new_file_name_buf));
;
//read pipe
char buf[4096] = {0};
//printf("reading ...\n");
if(read(sys.fd[0],buf,sizeof(buf) - 1) <= 0)
if(errno != EAGAIN || errno != EINTR)
break;
fwrite(buf,strlen(buf),1,fs);
}
}
//printf("while out...\n");
fclose(fs);
}
}
static void write_log(){
}
///initialize log processes
void init_log(int level)
{
log_level = level;
if(pipe(sys.fd) == -1){
printf("pipe for sys log error errno=%d,%s\n"
,errno,strerror(errno));
}
else{
pid_t pid;
pid = fork();
if(0 == pid)
{
printf("Log process run.\n");
///do the work..
pthread_t id1,id2;
close(sys.fd[1]);//close write
//if(NULL != sys.stream[1])
// fclose(sys.stream[1]);
//sys.stream[0] = fdopen(sys.fd[0],"a");
pthread_create(&id1,NULL,(void*(*)(void*))get_log,NULL);
pthread_join(id1,NULL);
//pthread_join(id2,NULL);
close(sys.fd[0]);//close read
//if(NULL != sys.stream[0])
// fclose(sys.stream[0]);
//printf("log process exit...\n");
exit(0);//child exit
}else if(pid < 0)///error
{
printf("fork error.errno=%d,%s\n",errno,strerror(errno));
}
else
{close(sys.fd[0]);
sys.stream[1] = fdopen(sys.fd[1],"a");
if(NULL == sys.stream[1])
{
printf("open FILE stream error,using buffer to write log,may be some data will lost.errno=%d [%s]\n",errno,strerror(errno));
}
}
}
}
void release_log(){
sys_log(1,"%s","<exit>");
close(sys.fd[1]);
if(NULL != sys.stream[1])
fclose(sys.stream[1]);
//int childs,countchild;
//while(1){
printf("waiting for child exit...\n");
wait(NULL);
//if(++countchild >= childs)
//break;
//}
}
</exit></errno></unistd></time></string></stdarg></sys></sys></sys></pthread></stdlib>
testlogger.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "logger.h"
//extern int log_level;
int main(int argc,char** argv){
if(argc > 1)
sscanf(argv[1],"%d",&log_level);
pid_t pa,pb;
int count = 0;
init_log(1);
char *a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n";
char *b = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n";
char *c = "cccccccccccccccccccccccccccccccc\n";
if((pa = fork()) == 0){
while(count < 5){
sys_log(1,"%s",a);
//usleep(1000);
++count;
}
exit(1);
}
else{
if((pb = fork()) == 0){
while(count < 5){
sys_log(2,"%s",b);
//usleep(1000);
++count;
}
exit(1);
}
}
while(count < 5){
log(3,"%s",c);
//usleep(1000);
++count;
}
//sys_log(1,"%s","<exit>");
//int status;
//waitpid(pa,&status,WEXITSTATUS);
//waitpid(pb,&status,WEXITSTATUS);
release_log();
printf("main process exit.\n");
return 0;
}
with extern "C"{}
[l@localhost code]$g++ -g -lpthread logger.c logger.h testlogger.c -o logger.exe
[l@localhost code]$ objdump --syms logger.exe
logger.exe: file format elf64-x86-64
SYMBOL TABLE:
0000000000400200 l d .interp 0000000000000000 .interp
000000000040021c l d .note.ABI-tag 0000000000000000 .note.ABI-tag
0000000000400240 l d .gnu.hash 0000000000000000 .gnu.hash
0000000000400268 l d .dynsym 0000000000000000 .dynsym
0000000000400520 l d .dynstr 0000000000000000 .dynstr
000000000040065a l d .gnu.version 0000000000000000 .gnu.version
0000000000400698 l d .gnu.version_r 0000000000000000 .gnu.version_r
00000000004006f8 l d .rela.dyn 0000000000000000 .rela.dyn
0000000000400710 l d .rela.plt 0000000000000000 .rela.plt
0000000000400980 l d .init 0000000000000000 .init
0000000000400998 l d .plt 0000000000000000 .plt
0000000000400b50 l d .text 0000000000000000 .text
0000000000401618 l d .fini 0000000000000000 .fini
0000000000401628 l d .rodata 0000000000000000 .rodata
0000000000401818 l d .eh_frame_hdr 0000000000000000 .eh_frame_hdr
0000000000401860 l d .eh_frame 0000000000000000 .eh_frame
0000000000601980 l d .ctors 0000000000000000 .ctors
0000000000601990 l d .dtors 0000000000000000 .dtors
00000000006019a0 l d .jcr 0000000000000000 .jcr
00000000006019a8 l d .dynamic 0000000000000000 .dynamic
0000000000601b78 l d .got 0000000000000000 .got
0000000000601b80 l d .got.plt 0000000000000000 .got.plt
0000000000601c70 l d .data 0000000000000000 .data
0000000000601ca8 l d .bss 0000000000000000 .bss
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l d .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l d .debug_pubnames 0000000000000000 .debug_pubnames
0000000000000000 l d .debug_info 0000000000000000 .debug_info
0000000000000000 l d .debug_abbrev 0000000000000000 .debug_abbrev
0000000000000000 l d .debug_line 0000000000000000 .debug_line
0000000000000000 l d .debug_frame 0000000000000000 .debug_frame
0000000000000000 l d .debug_str 0000000000000000 .debug_str
0000000000000000 l d .debug_loc 0000000000000000 .debug_loc
0000000000400b7c l F .text 0000000000000000 call_gmon_start
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000601980 l O .ctors 0000000000000000 __CTOR_LIST__
0000000000601990 l O .dtors 0000000000000000 __DTOR_LIST__
00000000006019a0 l O .jcr 0000000000000000 __JCR_LIST__
0000000000601ca8 l O .bss 0000000000000008 dtor_idx.6147
0000000000601cb0 l O .bss 0000000000000001 completed.6145
0000000000400ba0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000400c00 l F .text 0000000000000000 frame_dummy
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000601988 l O .ctors 0000000000000000 __CTOR_END__
0000000000401978 l O .eh_frame 0000000000000000 __FRAME_END__
00000000006019a0 l O .jcr 0000000000000000 __JCR_END__
00000000004015e0 l F .text 0000000000000000 __do_global_ctors_aux
0000000000000000 l df *ABS* 0000000000000000 logger.c
0000000000000000 l df *ABS* 0000000000000000 testlogger.c
000000000060197c l .ctors 0000000000000000 .hidden __preinit_array_start
000000000060197c l .ctors 0000000000000000 .hidden __fini_array_end
0000000000601b80 l O .got.plt 0000000000000000 .hidden _GLOBAL_OFFSET_TABLE_
000000000060197c l .ctors 0000000000000000 .hidden __preinit_array_end
000000000060197c l .ctors 0000000000000000 .hidden __fini_array_start
000000000060197c l .ctors 0000000000000000 .hidden __init_array_end
000000000060197c l .ctors 0000000000000000 .hidden __init_array_start
00000000006019a8 l O .dynamic 0000000000000000 .hidden _DYNAMIC
0000000000601c70 w .data 0000000000000000 data_start
0000000000000000 F *UND* 00000000000000a2 printf@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000b1b memset@@GLIBC_2.2.5
0000000000401540 g F .text 0000000000000002 __libc_csu_fini
0000000000000000 F *UND* 000000000000008b snprintf@@GLIBC_2.2.5
0000000000400b50 g F .text 0000000000000000 _start
0000000000000000 F *UND* 000000000000006c close@@GLIBC_2.2.5
0000000000000000 F *UND* 000000000000008e wait@@GLIBC_2.2.5
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses
0000000000000000 F *UND* 000000000000018c puts@@GLIBC_2.2.5
0000000000000000 F *UND* 00000000000000f1 exit@@GLIBC_2.2.5
0000000000401618 g F .fini 0000000000000000 _fini
0000000000000000 F *UND* 0000000000000080 read@@GLIBC_2.2.5
0000000000000000 F *UND* 000000000000000a fopen@@GLIBC_2.2.5
0000000000000000 F *UND* 00000000000001a5 __libc_start_main@@GLIBC_2.2.5
0000000000400d12 g F .text 0000000000000494 _Z7get_logPv
0000000000401628 g O .rodata 0000000000000004 _IO_stdin_used
0000000000601c70 g .data 0000000000000000 __data_start
0000000000000000 F *UND* 0000000000000c5f pthread_create@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000090 sscanf@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000025 pipe@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000160 pthread_join@@GLIBC_2.2.5
0000000000000000 F *UND* 00000000000000b9 strerror@@GLIBC_2.2.5
0000000000400c28 g F .text 00000000000000ea init_log
00000000004013e4 g F .text 000000000000003e release_log
0000000000401630 g O .rodata 0000000000000000 .hidden __dso_handle
0000000000601c90 g O .data 0000000000000018 sys
0000000000601998 g O .dtors 0000000000000000 .hidden __DTOR_END__
0000000000401550 g F .text 000000000000008b __libc_csu_init
0000000000601c80 g O .data 0000000000000004 log_level
0000000000000000 F *UND* 00000000000000e4 vsnprintf@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000011 __errno_location@@GLIBC_2.2.5
0000000000601ca8 g *ABS* 0000000000000000 __bss_start
0000000000000000 F *UND* 0000000000000021 strcmp@@GLIBC_2.2.5
0000000000601cb8 g *ABS* 0000000000000000 _end
0000000000000000 F *UND* 0000000000000206 fclose@@GLIBC_2.2.5
00000000004011a6 g F .text 000000000000023d sys_log
0000000000000000 F *UND* 0000000000000005 fork@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000163 fwrite@@GLIBC_2.2.5
0000000000601ca8 g *ABS* 0000000000000000 _edata
0000000000400af8 F *UND* 00000000000004bf __gxx_personality_v0@@CXXABI_1.3
0000000000000000 F *UND* 0000000000000011 localtime@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000080 write@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000025 mkdir@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000012 time@@GLIBC_2.2.5
0000000000401424 g F .text 0000000000000112 main
0000000000400980 g F .init 0000000000000000 _init