/****************************************************************************** 版权所有: 文件名称: rt_log.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2020-6-18 功能说明: 日志记录 其它说明: 没有资源竞争保护处理,只能在大循环级别使用。 修改记录: */ #include #include "my_rtc.h" #include struct log_file g_log_file[] = { {"/app/data/log_err.txt", 50*1024,0,0}, {"/app/data/log_operate.txt", 50*1024,0,0}, {"/app/data/log_soe.txt", 50*1024,0,0}, {"/app/data/log_yx.txt", 50*1024,0,0}, {"/app/data/log_printf.txt", 100*1024,0,0}, }; #define LOG_FILE_NUM ((int)(sizeof(g_log_file)/sizeof(g_log_file[0]))) #define LOG_FILE_BUFSIZE 1024 int g_logfile_update[LOG_FILE_NUM]; static char writebuf[LOG_FILE_NUM][LOG_FILE_BUFSIZE]; //数据缓存区 static int writebuf_count[LOG_FILE_NUM]; //缓存已存字节数 static char g_malloc_buf[LOG_FILE_NUM][LOG_FILE_BUFSIZE]; //数据缓存区 sem_t log_sem_buf[LOG_FILE_NUM]; // 信号量 对空指针进行读写操作会导致编译错误 static sem_t *log_sem[LOG_FILE_NUM]; int sem_for_type = 0; int log_init(void) { int i,j,file_length,max_length; char * file_buf; off_t pos; int err,ret; int len; pos=0; //找到最大的文件长度 max_length = 0; for(i = 0; i< LOG_FILE_NUM; i++) { log_sem[i]=&log_sem_buf[i]; if(g_log_file[i].size > max_length) { max_length = g_log_file[i].size; } writebuf_count[i] = 0; //清零 //if(sem_init(log_sem[i], sem_for_type, 0)) if(sem_init(log_sem[i], sem_for_type, 1)) //先创建一个1值信号量 return -1; } //分配内存 file_buf = (char *)rt_malloc(max_length); if(file_buf == NULL) { return -111; } //循环打开文件,找到00的位置 err = 0; for(i = 0; i< LOG_FILE_NUM; i++) { //打开文件 g_log_file[i].handle = rt_file_open(g_log_file[i].name, O_CREAT|O_RDWR, 0); if(IS_ERR(g_log_file[i].handle)) { printf("%s open error!\r\n",g_log_file[i].name); err++; continue; } len = rt_file_getfile_size(g_log_file[i].handle); if(len < 0) { printf("%s fstat error!\r\n", g_log_file[i].name); rt_file_close(g_log_file[i].handle, 0); g_log_file[i].handle = -1; err++; continue; } //得到文件长度 file_length = len; //读出文件内容 pos = 0; ret = rt_file_read(g_log_file[i].handle, file_buf, file_length, &pos); if(ret != file_length) //读出log内容 { rt_file_close(g_log_file[i].handle, 0); g_log_file[i].handle = -1; printf("%s read error:file_length=%d,ret=%d!\r\n",g_log_file[i].name,file_length,ret); err++; continue; } g_log_file[i].offset = 0; //如果文件长度,偏移量为0 if(file_length == 0) { g_log_file[i].offset = 0; continue; } //找到00位置,得到偏移量 for(j = 0; j < file_length-1; j++) { if(file_buf[j] == 0 && (file_buf[j+1] == 0)) { g_log_file[i].offset = j+1; break; } } } //释放内存 rt_free(file_buf); log_str_time(LOG_ERR,"装置上电",1,1); memset (g_logfile_update, 0, sizeof(g_logfile_update)); return -err; } //退出函数 int log_exit(void) { int i; //循环关闭文件 for(i = 0; i< LOG_FILE_NUM; i++) { if(log_sem[i]) { sem_destroy(log_sem[i]); log_sem[i] = NULL; } if(g_log_file[i].handle != 0) { rt_file_close(g_log_file[i].handle, 0); g_log_file[i].handle = -1; } } return 0; } static int _log_str(int index, char *log_buf,int log_len) { char flag[2],*buf,read_buf[2]; int end_len,over_len,file_length; off_t pos; off_t write_pos; int write_len; int tmp = 0; int ret=0; if(log_len == 0) { return 0; } if(log_len > LOG_FILE_BUFSIZE) { return -1; } // 检查参数 if(index > LOG_FILE_NUM) { return -1; } if(g_log_file[index].handle < 0) { return -2; } if(log_buf == NULL) { return -3; } //初始化 end_len = 0; over_len = 0; memset(flag,0x0,sizeof(flag)); pos=g_log_file[index].offset; buf=g_malloc_buf[index]; //判断是否记录长度超过文件长度 if(g_log_file[index].offset + log_len + 6 >= g_log_file[index].size) { //得到最后剩余的长度 end_len = g_log_file[index].size-g_log_file[index].offset; memset(buf,0,end_len); //将最后部分填0 if(rt_file_write(g_log_file[index].handle,buf,end_len,&pos) != end_len) { return -5; } //从头开始写入 pos = 0; } write_pos = pos; pos = pos + 2 + log_len + 2; g_log_file[index].offset = pos-1; pos += 2; write_len = 2 + log_len + 2 + 2; memcpy(buf, "\r\n", 2); tmp += 2; memcpy(buf+tmp, log_buf, log_len); tmp += log_len; memcpy(buf+tmp, flag, 2); tmp += 2; memcpy(buf+tmp, "\r\n", 2); memcpy(writebuf[index], buf, write_len); //在文件长度小于最大长度时,需要找到当前文件长度 fsync(g_log_file[index].handle); file_length = rt_file_getfile_size(g_log_file[index].handle); rt_file_llseek(g_log_file[index].handle, 0, SEEK_SET); //从换行后开始查找,找到被覆盖剩余记录部分长度 pos = g_log_file[index].offset + 3; while(pos <= (file_length - 2)) { if(rt_file_read(g_log_file[index].handle,read_buf, 2,&pos) != 2) { rt_printf("%s read error!\r\n",g_log_file[index].name); ret = -10; goto END; } if(read_buf[0] == 0 && read_buf[1] != 0) { break; } pos -= 1; } over_len = pos - g_log_file[index].offset - 4; if(over_len < 0) { goto END; } //将被覆盖剩余记录填0 memset(writebuf[index]+write_len,0,over_len); write_len += over_len; END: if(rt_file_write(g_log_file[index].handle,writebuf[index],write_len,&write_pos) != write_len) { rt_printf("%s write error!\r\n",g_log_file[index].name); return -12; } // 文件已更新 g_logfile_update[index] = 1; return ret; } int log_str(int index, char *log_buf) { int ret = 0,len; len = strlen(log_buf); sem_wait(log_sem[index]); ret = _log_str(index, log_buf,len); //写内容到文件 sem_post(log_sem[index]); return ret; } int log_str_len(int index, char *log_buf,int len) { int ret = 0; sem_wait(log_sem[index]); ret = _log_str(index, log_buf,len); //写内容到文件 sem_post(log_sem[index]); return ret; } static int log_str_flush(int index, char *log_buf, int log_len) { char flag[2],*buf,read_buf[2]; int end_len,over_len,file_length; off_t pos; if(log_len == 0) { return 0; } // 检查参数 if(index > LOG_FILE_NUM) { return -1; } if(g_log_file[index].handle == 0) { return -2; } if(log_buf == NULL) { return -3; } //初始化 end_len = 0; over_len = 0; memset(flag,0x0,sizeof(flag)); //log_len = strlen(log_buf); pos=g_log_file[index].offset; //判断是否记录长度超过文件长度 if(g_log_file[index].offset + log_len >= g_log_file[index].size) { //得到最后剩余的长度 end_len = g_log_file[index].size-g_log_file[index].offset; //分配内存 buf = (char *)rt_malloc(end_len); if(buf == 0) { return -4; } memset(buf,0,end_len); //将最后部分填0 if(rt_file_write(g_log_file[index].handle,buf,end_len,&pos) != end_len) { rt_free(buf); return -5; } rt_free(buf); //从头开始写入 pos = 0; } //写文件 if(rt_file_write(g_log_file[index].handle,log_buf, log_len ,&pos) != log_len) { return -9; } g_log_file[index].offset = pos-3; //在文件长度小于最大长度时,需要找到当前文件长度 fsync(g_log_file[index].handle); file_length= rt_file_getfile_size(g_log_file[index].handle); rt_file_llseek(g_log_file[index].handle, 0, SEEK_SET); //rt_free(buf); //从换行后开始查找,找到被覆盖剩余记录部分长度 pos = g_log_file[index].offset + 3; while(pos <= (file_length - 2)) { if(rt_file_read(g_log_file[index].handle,read_buf, 2,&pos) != 2) { rt_printf("%s read error!\r\n",g_log_file[index].name); return -10; } if(read_buf[0] == 0 && read_buf[1] != 0) { break; } pos -= 1; } over_len = pos - g_log_file[index].offset - 4; if(over_len < 0) { goto END; } //分配内存 buf = (char *)rt_malloc(over_len); if(buf == 0) { return -11; } memset(buf,0,over_len); pos = g_log_file[index].offset + 3; //将被覆盖剩余记录填0 if(rt_file_write(g_log_file[index].handle,buf,over_len,&pos) != over_len) { rt_free(buf); rt_printf("%s write error!\r\n",g_log_file[index].name); return -12; } rt_free(buf); END: // 文件已更新 g_logfile_update[index] = 1; return 0; } int log_str_ext(int index, char *log_buf) { int log_len= strlen(log_buf); sem_wait(log_sem[index]); //缓存数据内容已经足够大,写到文件中 if((log_len+3+writebuf_count[index]) >= LOG_FILE_BUFSIZE) { //最后一行结束字符00 00 0D 0A writebuf[index][writebuf_count[index]-2]=0; writebuf[index][writebuf_count[index]-1]=(unsigned char)'\r'; writebuf[index][writebuf_count[index]]=(unsigned char)'\n'; //写到文件中 log_str_flush(index, writebuf[index], writebuf_count[index]+1); writebuf_count[index] = 0;//清零 } //文件开头填充0D 0A if(writebuf_count[index]==0) { //数据末尾00 00 0D 0A //填充 0D 0A 数据 writebuf[index][0] = '\r'; writebuf[index][1] = '\n'; writebuf_count[index] += 2; } //缓存数据内容 memcpy(writebuf[index]+writebuf_count[index], log_buf, log_len); writebuf_count[index] += log_len; //一行内容以 00 0D 0A作为结束 writebuf[index][writebuf_count[index] ] = 0; writebuf_count[index] ++; memcpy(writebuf[index]+writebuf_count[index], "\r\n", 2); writebuf_count[index] +=2; sem_post(log_sem[index]); return 0; } void log_str_ext_flush(int index) { sem_wait(log_sem[index]); if(writebuf_count[index] > 0) { //结束字符00 00 0D 0A writebuf[index][writebuf_count[index]-2]=0; writebuf[index][writebuf_count[index]-1]=(unsigned char)'\r'; writebuf[index][writebuf_count[index]]=(unsigned char)'\n'; log_str_flush(index, writebuf[index], writebuf_count[index]+1); writebuf_count[index] = 0; } sem_post(log_sem[index]); } int log_str_time(int index, char *log_buf,int is_rtc,u8 val) { char * wirte_buf; int log_len; struct timespec ts={0,0}; struct rtc_time_t tm; #if 0 //jack.liu 20200911 获取rtc时间失能 if(is_rtc) // 装置上电时才用到 { // rtc_time_read(&tm); } else #endif { clk_time_get(&ts); timespec_to_rtc(ts,&tm,0); } // 检查参数 if(index > LOG_FILE_NUM) { return -1; } if(log_buf == NULL) { return -2; } //得到待写入字符串长度 log_len = strlen(log_buf)+16; wirte_buf = (char *)rt_malloc(log_len+strlen("2020-07-01 01:01:01.000000 ")); if((wirte_buf) == NULL) { return -1; } //得到系统时间 sprintf(wirte_buf,"20%02hu-%02hu-%02hu %02hu:%02hu:%02hu.%06lu ", tm.year,tm.month,tm.day,tm.hour,tm.min,tm.ms/1000,ts.tv_nsec/1000); strcat(wirte_buf,log_buf); log_str(index,wirte_buf); rt_free(wirte_buf); return 0; } int log_file_check(s8 * name) { int i; for(i=0; i= LOG_FILE_NUM) { return 1; } if(g_log_file[index].handle == 0) { return 1; } //得到文件长度 fsync(g_log_file[index].handle); file_length= rt_file_getfile_size(g_log_file[index].handle); rt_file_llseek(g_log_file[index].handle, 0, SEEK_SET); if(g_log_file[index].offset + 128 > g_log_file[index].size) { return 1; } return 0; }