Android和DLT日志系统

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);
}
写的off存在logger_log中(即内核内存buffer),而r_off存在于读的进程中,所以执行两次不同的logcat,都是从头开始读的。

1.2 logd日志进程
1.2.1 Android 8.0 per-tag
setprop log.tag.<tagname> DEBUG
/data/local.prop

logcat <tagname>:D *:S &

1.2.2 logwrapper
logwrapper /system/bin/mytest
或者
service logwrapper /system/bin/logwrapper /system/bin/mytest
    user root
    group root
    seclabel u:r:init:s0
    oneshot

logwrapper - 将被执行进程的stdio重定向到logd进程,然后通过logcat查看log。

1.2.3 调整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.4 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.3 Linux printk
1.3.1 printk的原理
printk的实现原理很简单,在有了日志消息后,首先申请控制台的信号量,如果申请到,则调用控制台写方法,写控制台。

在内核源码树的kernel/printk.c中,使用宏DECLARE_MUTEX声明了一个互斥锁console_sem,他用于保护console驱动列表console_drivers及同步对整个console驱动系统的访问。其中定义了函数acquire_console_sem来获得互斥锁console_sem,定义了release_console_sem来释放互斥锁console_sem,定义了函数try_acquire_console_sem来尽力得到互斥锁console_sem。这三个函数实际上是分别对函数down,up和down_trylock的简单包装。需要访问console_drivers驱动列表时就需要使用acquire_console_sem来保护console_drivers列表,当访问完该列表后,就调用release_console_sem释放信号量console_sem。函数console_unblank,console_device,console_stop,console_start,register_console 和unregister_console都需要访问console_drivers,因此他们都使用函数对acquire_console_sem和release_console_sem来对console_drivers进行保护。

调试console_sem时,需要打开宏CONFIG_DEBUG_SPINLOCK以跟踪owner字段。

关闭kernel Log,通过bootchart.png可以看到启动init进程的时间明显提前,可以加快启动速度。
kernel/printk.c
int console_printk[4] = {
    DEFAULT_CONSOLE_LOGLEVEL,
    DEFAULT_MESSAGE_LOGLEVEL,
    MINIMUM_CONSOLE_LOGLEVEL,
    DEFAULT_CONSOLE_LOGLEVEL,
};
改为
int console_printk[4] = {
    0, //DEFAULT_CONSOLE_LOGLEVEL,
    0, //DEFAULT_MESSAGE_LOGLEVEL,
    0, //MINIMUM_CONSOLE_LOGLEVEL,
    0, //DEFAULT_CONSOLE_LOGLEVEL,
};
这四个值对应到路径proc/sys/kernel/printk,当printk()没有指定消息级别时,就采用DEFAULT_MESSAGE_LOGLEVEL(对应到KERN_WARNING = 4)。

echo "8 8 8 8" > /proc/sys/kernel/printk

Android中logcat读取dmesg后,不显示最前面的时间戳,所以不方便查找内核时间,可以使用如下的方式,在每次调用打印函数时,同时也打印下面的秒和微妙2个值,这样logcat读取的dmesg就不会丢失内核时间点 (28-Dec-2021)。
static void get_timestamp(
    u64 *sec, u64 *usec)
{
    u64 ts;
    u64 rem_ns;

    ts = local_clock();
    rem_ns = do_div(ts, 1000000000);
    /* %5lu */
    *sec = ts;
    /* %06lu */
    *usec = rem_ns / 1000;
}

1.3.2 修改Android Printk默认loglevel
修改这个值前,检查一下init中允许的最大值,否则改为8可能无效。

in init.rc
change
loglevel 3
to
loglevel 6

1.3.3 重定向服务stdio到/dev/console
init.xx.rc
service xxx /system/bin/xxx
    class main
    console # 将服务xxx的stdio定向到/dev/console,否则到/dev/null

1.3.4 pr_debug动态log
CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y

echo "file my_drv.c +p" > \
/sys/kernel/debug/dynamic_debug/control

1.4 Linux pstore - Persistent Storage
主要用于存储内核异常时的log信息。实现方式是,管理一块“非易失性的存储空间”,如不断电的RAM或外部存储,当系统异常时,将log信息写到Pstore管理的存储空间,直到下一次系统正常时,再将log读出来,以文件形式提供给用户使用。

1.5 Linux logrotate
当第一次进行日志轮替时,当前的secure日志会自动改名为secure.1,然后新建secure日志,用来保存新的日志;当第二次进行日志轮替时,secure.1会自动改名为secure.2,当前的secure日志会自动改名为secure.1,然后也会新建secure日志,用来保存新的日志;以此类推。

2 GENIVI DLT
2.1 GENIVI systemd configuration file
/etc/systemd/system
/lib/systemd/system
/run/systemd/system
/usr/lib/systemd/user

2.2 commands
systemctl list-unit-files | grep enable

systemctl cat dlt-daemon.service
systemctl cat dlt-system.service

systemctl show dlt-daemon.service
systemctl show dlt-system.service

systemctl start dlt-recv-daemon.service

2.3 dlt viewer
/etc/dlt.conf
dlt viewer可以通过TCP、UDP和串口连接dlt daemon。

2.4 showcase
[21-Oct-2021]
dlt-receive -a localhost

2.5 DLT memory monitor
This is used to check OOM issue.
oom-killer: GFP_HIGHUSER_MOVABLE
Application ID: MON
Context ID: MSER
Context ID: THRD
The 1st para: timestamp
The 5th para: pgfault
The 8th para: active_anon

3 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;

/* char dropped count */
static unsigned int cdc = 0;
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);
}

4 Abbreviations
bail out:跳伞
dlt: Diagnostic Log and Trace
Slog.wtf:what a terrible failure
usr: Unix System Resource

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/968207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI赋能】蓝耘智算平台实战指南:3步构建企业级DeepSeek智能助手

蓝耘智算平台实战指南&#xff1a;3步构建企业级DeepSeek智能助手 引言&#xff1a;AI大模型时代的算力革命 在2025年全球AI技术峰会上&#xff0c;DeepSeek-R1凭借其开源架构与实时推理能力&#xff0c;成为首个通过图灵测试的中文大模型。该模型在语言理解、跨模态交互等维…

Mac(m1)本地部署deepseek-R1模型

1. 下载安装ollama 直接下载软件&#xff0c;下载完成之后&#xff0c;安装即可&#xff0c;安装完成之后&#xff0c;命令行中可出现ollama命令 2. 在ollama官网查看需要下载的模型下载命令 1. 在官网查看deepseek对应的模型 2. 选择使用电脑配置的模型 3. copy 对应模型的安…

第七节 文件与流

基本的输入输出&#xff08;iostream&#xff09; C标准库提供了一组丰富的输入/输出功能&#xff0c;C的I/O发生在流中&#xff0c;流是字节序列。如果字节流是从设备&#xff08;键盘、磁盘驱动器、网络连接等&#xff09;流向内存&#xff0c;叫做输入操作。如果字节流是从…

网络安全溯源 思路 网络安全原理

网络安全背景 网络就是实现不同主机之间的通讯。网络出现之初利用TCP/IP协议簇的相关协议概念&#xff0c;已经满足了互连两台主机之间可以进行通讯的目的&#xff0c;虽然看似简简单单几句话&#xff0c;就描述了网络概念与网络出现的目的&#xff0c;但是为了真正实现两台主机…

内网ip网段记录

1.介绍 常见的内网IP段有&#xff1a; A类&#xff1a; 10.0.0.0/8 大型企业内部网络&#xff08;如 AWS、阿里云&#xff09; 10.0.0.0 - 10.255.255.255 B类&#xff1a;172.16.0.0/12 中型企业、学校 172.16.0.0 - 172.31.255.255 C类&#xff1a;192.168.0.0/16 家庭…

SQL Server 逻辑查询处理阶段及其处理顺序

在 SQL Server 中&#xff0c;查询的执行并不是按照我们编写的 SQL 语句的顺序进行的。相反&#xff0c;SQL Server 有自己的一套逻辑处理顺序&#xff0c;这个顺序决定了查询的执行方式和结果集的生成。了解这些处理阶段和顺序对于优化查询性能和调试复杂查询非常重要。 SQL …

四、OSG学习笔记-基础图元

前一章节&#xff1a; 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码&#xff1a;CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…

性格测评小程序03搭建用户管理

目录 1 创建数据源2 搭建后台3 开通权限4 搭建启用禁用功能最终效果总结 性格测评小程序我们期望是用户先进行注册&#xff0c;注册之后使用测评功能。这样方便留存用户的联系信息&#xff0c;日后还可以推送对应的相关活动促进应用的活跃。实现这个功能我们要先创建数据源&…

Ubuntu 如何安装Snipaste截图软件

在Ubuntu上安装Snipaste-2.10.5-x86_64.AppImage的步骤如下&#xff1a; 1. 下载Snipaste AppImage 首先&#xff0c;从Snipaste的官方网站或GitHub Releases页面下载Snipaste-2.10.5-x86_64.AppImage文件。 2. 赋予执行权限 下载完成后&#xff0c;打开终端并导航到文件所在…

突破与重塑:逃离Java舒适区,借Go语言复刻Redis的自我突破和成长

文章目录 写在文章开头为什么想尝试用go复刻redis复刻redis的心路历程程序员对于舒适区的一点看法关于mini-redis的一些展望结语 写在文章开头 在程序员的技术生涯长河中&#xff0c;我们常常会在熟悉的领域中建立起自己的“舒适区”。于我而言&#xff0c;Java 就是这片承载…

【自然语言处理】TextRank 算法提取关键词、短语、句(Python源码实现)

文章目录 一、TextRank 算法提取关键词 [工具包]二、TextRank 算法提取关键短语[工具包]三、TextRank 算法提取关键句[工具包]四、TextRank 算法提取关键句&#xff08;Python源码实现&#xff09; 一、TextRank 算法提取关键词 [工具包] 见链接 【自然语言处理】TextRank 算法…

展厅为何倾向使用三维数字沙盘进行多媒体互动设计?优势探讨!

随着数字技术的迅猛进步&#xff0c;展厅多媒体互动设计正迎来深刻变革。其中&#xff0c;三维数字沙盘作为经典沙盘模型的革新之作&#xff0c;不仅保留了其空间布局直观展示的优点&#xff0c;更巧妙融入光影互动与中控系统&#xff0c;推动展览展示向智能化迈进。今日&#…

SDKMAN! 的英文全称是 Software Development Kit Manager(软件开发工具包管理器)

文章目录 SDKMAN! 的核心功能SDKMAN! 的常用命令SDKMAN! 的优势总结 SDKMAN! 的英文全称是 Software Development Kit Manager。它是一个用于管理多个软件开发工具&#xff08;如 Java、Groovy、Scala、Kotlin 等&#xff09;版本的工具。SDKMAN! 提供了一个简单的方式来安装、…

java配置api,vue网页调用api从oracle数据库读取数据

一、主入口文件 1&#xff1a;java后端端口号 2&#xff1a;数据库类型 和 数据库所在服务器ip地址 3&#xff1a;服务器用户名和密码 二、映射数据库表中的数据 resources/mapper/.xml文件 1&#xff1a;column后变量名是数据库中存储的变量名 property的值是column值的…

蓝桥杯C语言组:分治问题研究

蓝桥杯C语言组分治问题研究 摘要 本文针对蓝桥杯C语言组中的分治问题展开深入研究&#xff0c;详细介绍了分治算法的原理、实现方法及其在解决复杂问题中的应用。通过对经典例题的分析与代码实现&#xff0c;展示了分治算法在提高编程效率和解决实际问题中的重要作用&#xff…

Golang GORM系列:GORM CRUM操作实战

在数据库管理中&#xff0c;CRUD操作是应用程序的主干&#xff0c;支持数据的创建、检索、更新和删除。强大的Go对象关系映射库GORM通过抽象SQL语句的复杂性&#xff0c;使这些操作变得轻而易举。本文是掌握使用GORM进行CRUD操作的全面指南&#xff0c;提供了在Go应用程序中有效…

如何评估云原生GenAI应用开发中的安全风险(下)

以上就是如何评估云原生GenAI应用开发中的安全风险系列中的上篇内容&#xff0c;在本篇中我们介绍了在云原生AI应用开发中不同层级的风险&#xff0c;并了解了如何定义AI系统的风险。在本系列下篇中我们会继续探索我们为我们的云原生AI应用评估风险的背景和意义&#xff0c;并且…

2025 年 2 月 TIOBE 指数

2025 年 2 月 TIOBE 指数 二月头条:快,更快,最快! 现在,世界需要每秒处理越来越多的数字,而硬件的发展速度却不够快,程序的速度变得越来越重要。话虽如此,快速编程语言在 TIOBE 指数中取得进展也就不足为奇了。编程语言 C++ 最近攀升至第 2 位,Go 已稳居前 10 名,Ru…

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492&#xff0c;我们详细探讨了YOLO11的部署以及推理训练&#xff0c;但是评论区的观众老爷就说了&#xff1a;“博主博主&#xff0c;你这个只能推理…

Segformer模型的平台部署和项目应用

最近因为离职太忙了之前的很多内容没有更新&#xff0c;离开BYD进入新的环境中成长。 本文包含了Segformer的网络结构重构后如何部署到算法平台中方便标注训练推理的过程&#xff0c;以及如何应用到项目中&#xff08;BYD最后一个项目&#xff1a;异物检测系统&#xff09; C做…