发布网友 发布时间:2022-11-20 10:06
共1个回答
热心网友 时间:2023-06-23 10:34
logd守护进程是日志系统的管家,内部维持三个日志 Socket: logd、logdr、logdw来与客户端进行通信。同时负责维护几个环形缓冲区,用于存放系统中的各种日志,缓冲区包含 main、system、events、radio、crash、kernel;但是在 Android 5.0之前,logd进程并不存在,日志是保留在 /dev/log/main、/dev/log/system、/dev/log/radio、/dev/log/event等节点中,但是这样面临的一个问题就是当 Android系统大版本升级时,linux kernel需要升级对应的日志驱动,因此在后续的版本中就有了 logd进程。
在 Android 日志系统分析(一):概述 一文中,总结了整个日志读写的主要流程,因此对于 logd进程是如何同外界沟通进而读写日志的过程不再赘述,而着重于 logd本身的一些知识点,这里先看一下 logd的系统框图:
知识点:
① logd是日志系统的核心进程,由 init启动,是属于守护进程常驻后台
② logd维护各个日志节点缓存队列,提供 socket接口进行读、写、控制功能
③ logd进程启动后,分别启动 LogReader、LogListener、CommandListener三个线程,监听并处理来自三个 socket的消息。在收到消息后,会通过 LogBuffer类保存日志到对应的 RAM buffer中
④ LogAudit模块用于接收 Kernel selinux信息,即可以在用户空间打印 selinux日志信息
⑤ LogKlog用于接收 kernel日志信息,通过设置 property,可以通过 logcat命令读取内核日志
⑥ LogStatistics是日志统计模块,默认开启统计数据较少,仅能以 pid/uid纬度统计打印日志的数量。如果设置了 logd.statistic = true。会打印更多纬度的统计信息,包括哪些 pid/uid/tid/TAG日志量比较大,可用于日志裁剪相关
在 main函数中,会打开 /dev/kmsg来读取内核日志,通过 LogKlog来进行存储;若是配置了 ro.logd.kernel属性,则打开 /proc/kmsg读取内核日志;
logd作为 Native Service,系统启动时会读取 init.rc脚本去启动,它的相关属性被定义在 logd.rc文件中:
这里主要分为两部分:启动 logd 服务和 启动 logd-reinit 服务(在Android 10 上添加了 logd-auditctl 服务,目的是为了* selinux denia打印日志为5秒一次);先来看一下 启动 logd 服务的同时做了些什么:
① 创建 logd、logdr、logdw这三个 socket为后面的通信做准备
② logdw定义为 dgram类型的 socket,类似与 UDP类型的 Socket,这么做的原因是考虑到性能问题,在多个进程同时写日志的情况下,write函数写入到 socket的 buffer中即可返回,这样不会 block业务逻辑太长时间。如果是 TCP类型的 Socket,客户端需要等到 TCP收到 ACK响应才能返回,这样就会过多的消耗性能和资源;
启动 logd-reinit 服务:
这个服务的主要作用是重新初始化 logd的 LogBuffer,在配置中 oneshot表示开机只启动一次。在上面的 main.cpp中的 main函数内,logd在启动后,会创建一个线程 reinit_thread_start (),当 logd-reinit传入参数 reinit后,进行功能执行:
① 如果 reinit启动后,并且 /deg/kmsg打开成功,把 logd.daemon: renit写入 kmsg
② 重新初始化各个 log buffer的大小,以及其他参数的初始化,但不会重新生成 LogBuffer对象
main.cpp##main
main.cpp#reinit_thread_start()
[ 1 ] 深入理解安卓日志系统(logcat / liblog / logd)
[ 2 ] Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化