1 Linux Android日志系统
1.1 内核logger机制
@ drivers/staging/android/logger.c
static size_t logger_offset(struct logger_log *log, size_t n)
{
return n & (log->size - 1);
}
Write的off存在logger_log中(即内核内存buffer),而r_off存在于读的进程中。所以执行两次不同的logcat,都是从头开始读的。
1.2 logd日志进程
1.2.1 Legacy
#ifndef LOG_PRI
#define LOG_PRI(priority, tag, ...) \
({ \
if (((priority == ANDROID_LOG_VERBOSE) && (LOG_NDEBUG == 0)) || \
((priority == ANDROID_LOG_DEBUG) && (LOG_NDDEBUG == 0)) || \
((priority == ANDROID_LOG_INFO) && (LOG_NIDEBUG == 0)) || \
(priority == ANDROID_LOG_WARN) || \
(priority == ANDROID_LOG_ERROR) || \
(priority == ANDROID_LOG_FATAL)) \
(void)android_printLog(priority, tag, __VA_ARGS__); \
})
#endif
对于WARN、ERROR、FATAL级别的log可以直接输出,而对于VERBOSE、DEBUG、INFO级别的log必需在定义相应宏的情况下才可以输出,所以需要在相应的文件中定义MACRO。
1.2.2 New ARCH
设置log等级环境变量:ANDROID_LOG_TAGS
全部打开
export ANDROID_LOG_TAGS="*:v"
全局过滤
export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D * :S"
1.2.3 logwrapper
logwrapper /system/bin/mytest
或者
service logwrapper /system/bin/logwrapper /system/bin/mytest
user root
group root
oneshot
logwrapper - 将被执行进程的stdio重定向到logd进程,然后通过logcat查看log。
1.2.4 调整logcat打印时间
diff --git a/liblog/logprint.c b/liblog/logprint.c
index c2f1545..75d095d 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -907,7 +907,10 @@ char *android_log_formatLogLine (
* brackets, asterisks, or other special chars here.
*/
#if !defined(_WIN32)
- ptm = localtime_r(&(entry->tv_sec), &tmBuf);
+ //ptm = localtime_r(&(entry->tv_sec), &tmBuf);
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ptm = localtime(&(tv.tv_sec));
#else
ptm = localtime(&(entry->tv_sec));
#endif
1.2.5 Logd不能打印dmesg
diff --git a/logd/main.cpp b/logd/main.cpp
index a3241d0..457be8e 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -277,6 +277,7 @@ static bool property_get_bool_svelte(const char *key) {
property_get("ro.build.type", property, "");
not_user = !!strcmp(property, "user");
}
+ not_user = true;
return property_get_bool(key, not_user
&& !property_get_bool("ro.config.low_ram", false));
}
1.2.6 URLs
log android调试神器
https://blog.csdn.net/by317966834/article/details/11892581
Android L日志系统1——logd
https://blog.csdn.net/koffuxu/article/details/53893297
1.3 Linux early_printk和early_console
1.4 Linux printk
四个重要变量:
static u64 log_first_seq; //指向当前可读的struct log 索引号
static u32 log_first_idx; //指向环形缓冲区可以读的位置
staticu64 log_next_seq; //指向当前可写的struct log 索引号
static u32 log_next_idx; //指向环形缓冲区可写的位置
@ init.xx.rc
service xxx /system/bin/xxx
class main
console // 将stdio定向到/dev/console,否则到/dev/null
1.5 Linux Pstore - Persistent Storage
主要用于存储内核异常时的log信息。实现方式是,管理一块“非易失性的存储空间”,如不断电的RAM或外部存储,当系统异常时,将log信息写到Pstore管理的存储空间,直到下一次系统正常时,再将log读出来,以文件形式提供给用户使用。
ramoops&pstore简要说明
https://blog.csdn.net/zangdongming/article/details/37729315
2 FreeRTOS简单log系统的实现
@ oem_log.c
#define USE_WAIT_QUEUE
#define TASK_BUF_SZ 2048
#define LINE_BUF_SZ 1024
#define LOG_BUF_SZ 4096
#define LOG_BUF_MASK (LOG_BUF_SZ - 1)
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
static unsigned char line_buf[LINE_BUF_SZ];
static unsigned char log_buf[LOG_BUF_SZ];
static unsigned int log_start = 0, con_start = 0;
static unsigned int log_end = 0;
static unsigned int cdc = 0; /* char dropped count */
static SemaphoreHandle_t log_sem = NULL;
#if 1
#define log_lock() do { \
if (NULL != log_sem) { \
xSemaphoreTake(log_sem, portMAX_DELAY); \
} \
} while (0)
#define log_unlock() do { \
if (NULL != log_sem) { \
xSemaphoreGive(log_sem); \
} \
} while (0)
#else
#define log_lock() do {} while(0)
#define log_unlock() do {} while(0)
#endif
#if 1
static int do_write_log2emmc(const char *buf, const uint16_t nbytes)
{
FIL fil;
FRESULT fr;
const char *bufp = buf;
uint16_t nleft, nwritten = 0;
uint8_t cnt = 0;
if (NULL == buf) {
return 0;
}
nleft = nbytes;
fr = f_open(&fil, LOG_FNAME, FA_OPEN_APPEND | FA_WRITE);
if (FR_OK == fr) {
while ((nleft > 0) && (cnt++ < 5)) {
fr = f_write(&fil, bufp, nleft, &nwritten);
if ((FR_OK == fr) && (nwritten > 0)) {
bufp += nwritten;
nleft -= nwritten;
}
}
cdc += nleft;
f_close(&fil);
}
if (nbytes == nleft) {
return -1;
}
return (nbytes - nleft);
}
#endif
static inline void emit_char(const uint8_t c)
{
LOG_BUF(log_end) = c;
log_end++;
if ((log_end - log_start) > LOG_BUF_SZ) {
log_start = log_end - LOG_BUF_SZ;
cdc++;
}
if ((log_end - con_start) > LOG_BUF_SZ) {
con_start = log_end - LOG_BUF_SZ;
}
}
int oem_sh_log(const char *buf, const char *fmt,...)
{
hal_rtc_time_t local_time = {0};
int16_t i, n, ts_len = 0;
#if defined (USE_WAIT_QUEUE)
uint8_t msg_id;
#endif
static uint32_t nr_data = 0;
va_list ap;
log_lock();
if (buf && (buf[0] != 0x55)) {
#if 1
n = do_write_log2emmc(buf, strlen(buf));
#endif
} else {
if (buf && (buf[0] == 0x55)) {
} else {
hal_rtc_get_time(&local_time);
ts_len = snprintf(line_buf, LINE_BUF_SZ, "[%d/%d/%d %02d:%02d:%02d]<%d> ",
local_time.rtc_year + 2000,
local_time.rtc_mon,
local_time.rtc_day,
local_time.rtc_hour,
local_time.rtc_min,
local_time.rtc_sec,
nr_data++);
}
va_start(ap, fmt);
if (ts_len > 0) {
n = vsnprintf(line_buf + ts_len, LINE_BUF_SZ - ts_len, fmt, ap);
} else {
n = vsnprintf(line_buf, LINE_BUF_SZ, fmt, ap);
}
va_end(ap);
if (n > 0) {
if (ts_len > 0) {
n += ts_len;
}
for (i = 0; i < n; i++) {
emit_char(line_buf[i]);
}
}
}
#if defined (USE_WAIT_QUEUE)
if ((log_end - log_start) >= (LOG_BUF_SZ - 1024)) {
msg_id = 1;
xQueueSend(task_wait_queue, &msg_id, 0);
}
#endif
log_unlock();
return n;
}
static void sh_log_task(void *data)
{
bool to_send;
unsigned char tbuf[TASK_BUF_SZ];
uint16_t i;
#if defined (USE_WAIT_QUEUE)
uint8_t msg_id;
#endif
while (1) {
log_lock();
#if 0
if (1 == (log_end - log_start)) {
log_start = 0;
log_end = 0;
} else
#endif
if (log_start < log_end) {
for (i = 0; (i < (TASK_BUF_SZ - 1)) && (log_start < log_end);
i++, log_start++) {
tbuf[i] = LOG_BUF(log_start);
}
tbuf[i] = '\0';
to_send = true;
}
log_unlock();
if (to_send) {
to_send = false;
// oem_log("%s", tbuf);
#if 1
do_write_log2emmc(tbuf, strlen(tbuf));
#endif
tbuf[0] = '\0';
}
#if defined (USE_WAIT_QUEUE)
// block here, don't care return value
xQueueReceive(p_slc_dev->task_wait_queue, &msg_id, (10000 / portTICK_PERIOD_MS));
#else
vTaskDelay(100 / portTICK_PERIOD_MS);
#endif
}
vTaskDelete(NULL);
}
LA和RTOS日志系统
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zoosenpin/article/details/78376363
猜你喜欢
转载自blog.csdn.net/zoosenpin/article/details/78376363
今日推荐
周排行