/****************************************************************************** 版权所有: 文件名称: 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}, {"/app/data/log_fixset.txt", 50 * 1024, 0, 0}, // {"/app/data/log_auth.txt", 10 * 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; i++) { if (strstr(name, g_log_file[i].name) == 0) { return i; } } return -1; } int log_file_is_overrun(int index) { int file_length; if (index >= 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; }