wirte函数在O_APPEND模式下,是线程安全的。所以使用线程读写锁,让写日志函数多并发运行。定时进入写模式刷新数据,并通过判断文件大小进行压缩备份。
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
#include <fcntl.h>
#define LOGADDR "test.log"
static int log_fd = -1;
static pthread_rwlock_t log_lock;
static void get_timestamp(char *buffer)
{
time_t t;
struct tm *p;
struct timeval tv;
int len;
int millsec;
t = time(NULL);
p = localtime(&t);
gettimeofday(&tv, NULL);
millsec = (int)(tv.tv_usec / 1000);
/* 时间格式:[2011-11-15 12:47:34:888] */
len = snprintf(buffer, 32, "[%04d-%02d-%02d %02d:%02d:%02d:%03d] ",\
p->tm_year+1900, p->tm_mon+1,\
p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, millsec);
buffer[len] = '\0';
}
int find_file(char *filename)
{
int rev = -1;
DIR *dir;
struct dirent *entry;
char path[1024]; // 存放路径字符串
int i = 1;
if((dir = opendir(".")) != NULL)
{
while ((entry = readdir(dir)) != NULL)
{
if(strcmp(filename, entry->d_name) == 0)
{
rev = 0;
break;
}
}
closedir(dir);
}
else
{
perror("无法打开目录");
return -1;
}
return rev;
}
//创建文件夹
static int create_dir(const char *sPathName)
{
char dirName[256];
strcpy(dirName, sPathName);
int i,len = strlen(dirName);
for(i=1; i<len; i++)
{
if(dirName[i]=='/')
{
dirName[i] = 0;
if(access(dirName, 0)!=0)
{
if(mkdir(dirName, 0755)==-1)
{
printf("mkdir error\n");
return -1;
}
}
dirName[i] = '/';
}
}
return 0;
}
int open_log(const char *filename)
{
int fd;
fd = open(filename, O_WRONLY | O_APPEND);
if(fd < 0)
{
printf("%s can't open\n", filename);
create_dir(filename);
fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0666);
if(fd < 0)
{
printf("%s can't open--2\n", filename);
}
}
return fd;
}
void *pthread_func1(void *arg)
{
int flag = 0;
char buff[100];
while(1)
{
flag = 0;
get_timestamp(buff);
printf("%s----pthread_rwlock_wrlock--\n", buff);
pthread_rwlock_wrlock(&log_lock);
get_timestamp(buff);
printf("%s----pthread_rwlock_wrlock-1--\n", buff);
if(log_fd < 0)
{
log_fd = open_log(LOGADDR);
// if(log_fd > 0)
// {
// off_t filesize = lseek(log_fd, 0, SEEK_END);
// if(filesize == 0)
// {
// write(log_fd, "new file\n", strlen("new file\n"));
// }
// }
}
else
{
fsync(log_fd);
off_t filesize = lseek(log_fd, 0, SEEK_END);
if(filesize > 1024*1024)
{
close(log_fd);
char cmd[1000];
flag = 1;
sprintf(cmd, "mv -f %s test_bak.log", LOGADDR);
printf("cmd:%s\n", cmd);
system(cmd);
log_fd = open_log(LOGADDR);
}
}
pthread_rwlock_unlock(&log_lock);
if(flag == 1)
{
int tar_no;
char cmd[1000];
for(tar_no=0; tar_no<10; tar_no++)
{
sprintf(cmd, "test_%d.tar.gz", tar_no);
if(find_file(cmd) < 0)
{
break;
}
}
sprintf(cmd, "tar -zcf test_%d.tar.gz test_bak.log", tar_no);
printf("cmd:%s\n", cmd);
system(cmd);
tar_no++;
if(tar_no >= 10) tar_no = 0;
sprintf(cmd, "rm -f test_%d.tar.gz", tar_no);
printf("cmd:%s\n", cmd);
system(cmd);
}
sleep(1);
}
}
void *pthread_func2(void *arg)
{
int no = *(int*)arg;
int i = 0;
char buf[1000];
while(1)
{
get_timestamp(buf);
sprintf(buf+strlen(buf), "pthread_func2--------------%d--%d-\n", no, i++);
printf("fd:%d-%s", log_fd, buf);
if(log_fd > 0)
{
pthread_rwlock_rdlock(&log_lock);
write(log_fd, buf, strlen(buf));
pthread_rwlock_unlock(&log_lock);
}
usleep(10000);
if(i>=9999) break;
}
}
// int find_file(char *filename)
// {
// int rev = -1;
// DIR *dir;
// struct dirent *entry;
// char path[1024]; // 存放路径字符串
// int i = 1;
// if((dir = opendir(".")) != NULL)
// {
// while ((entry = readdir(dir)) != NULL)
// {
// if(strcmp(filename, entry->d_name) == 0)
// {
// rev = 0;
// break;
// }
// }
// closedir(dir);
// }
// else
// {
// perror("无法打开目录");
// return -1;
// }
// return rev;
// }
// int file_touch(void)
// {
// int i = 0;
// char filename[200];
// char cmd[1000];
// for(i=0; i<50; i++)
// {
// sprintf(filename, "file_%d.log", i);
// if(find_file(filename) < 0)
// {
// break;
// }
// }
// sprintf(cmd, "touch %s", filename);
// printf("%s\n", cmd);
// system(cmd);
// i++;
// if(i>= 50)
// {
// i = 0;
// }
// sprintf(cmd, "rm -r file_%d.log", i);
// printf("%s\n", cmd);
// system(cmd);
// }
int main(void)
{
int i;
int num = 8;
pthread_t threads[10];
int list[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
pthread_rwlockattr_t attr;
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&log_lock, &attr);
pthread_create(threads, NULL, pthread_func1, NULL);
for(i=1; i<num; i++)
pthread_create(threads+i, NULL, pthread_func2, &list[i]);
for(i=0; i<num; i++)
pthread_join(threads[i], NULL);
// for(i=0; i<101; i++)
// {
// file_touch();
// }
return 0;
}