A,General introduction
Android Log system is a module that developers are familiar with. Every developer uses log. d interface to print logs during development, and uses logcat to view the printed logs to locate problems. In this paper, through in-depth analysis of the log system related modules and source code, so that developers have a deeper understanding of the printing log and log storage related technology principle, so as to make more efficient use of the log system.
This article introduces the Android logging system in user space, excluding Linux Kernel logs. It also does not include the process for collecting crash/ANR/tombstone/kernel panic logs.
This article is based on Android 9.0 system source code. Liblog and Logd have little difference between Android 10 and Android 11. Although logcat has been refactored in C++ for Android 10, the interface to its basic business logic remains the same. It should be noted that this paper does not emphasize the specific code logic, but analyzes from the perspective of design, focusing on clarifying the interface before the module and the basic functions of the corresponding module.
1.1 System Framework
The Android log system is shown from top to bottom:
- Application layer interface:
In the application layer, Android system encapsulates the Java interface of the Log system, log. Java, rlog. Java, slog. Java eventlog. Java. Application developers are familiar with log.java, while system developers are familiar with Rlog, Slog, EventLog interfaces. The functions of these interfaces are similar in that they write logs. The difference is that the log nodes that write logs to logd are different.
The Java interface is encapsulated in Android. jar and provided to developers as an SDK. Native API of the system is called through the JNI interface in libAndroid_runtime. so at runtime.
For C/C++ developers, you can directly use the ALOGD and other apis provided in log.h to print logs in native programs.
- native api
Log system core service logd, a native daemon. To access the API provided by LogD, Android encapsulates a layer of Liblog to facilitate the application layer to access logD socket API
- Core logd
Logd is the core of the log system. It is started by the Init process and runs continuously in the background of the system. Logd maintains a RAM buffer that serves as a cache for logs. The logs of each process are written to this RAM buffer. If too many logs are written, the oldest logs are deleted using an algorithm similar to the ring buffer logic.
Logd maintains three SOCKET apis:
-
Dev /socket/logd Transfer control instruction
-
/ dev/socket logw writing log
-
Dev/socket/logr reading log
- native bin
In the Native layer, Android provides a /system/bin/logcat native command line program as a unified client communication process. Adb Logcat allows developers to read logs or send commands to logd.
1.2 System Design
By design, the logging system module is a typical producer-consumer model of the system:
-
Individual client processes are log producers;
-
Logcat is the consumer of the log and can contain multiple consumer processes;
-
The message queue is a Ring buffer. If the message queue exceeds the threshold, logs are cut down.
Functional constraints that a module needs to provide:
-
Cross-process access: Multiple processes can concurrently read and write data.
-
Provide interfaces for each module to read and write logs;
-
Log buffers can be stored in different categories.
-
Decoupled design with Kernel, etc
Before Android 5.0, the logd process does not exist, and logs are reserved for various nodes such as /dev/log/main, /dev/log/system, /dev/log/radio, and /dev/log/event. However, this requires that the Linux Kernel needs to be upgraded every time the Android major version is upgraded. Therefore, Google reconstructed the log system and created a logd process to retain logs on the client.
Second,Log writing process analysis
The process of writing to the log is actually the process of the client sending a message via dev/socket/logdw,
The detailed process is as follows:
- The client process writes logs through the interface provided in the SDK.
The d (TAG, "the Message body");Copy the code
- Java code calls liblog through JNI;
android_util_Log_println_native
Copy the code
- Liblog encapsulates the socket interface for logD access. Liblog through socket communication, complete client log writing logD;
__android_log_buf_write
write_to_log
__write_to_log_init
__write_to_log_daemon
write_transport_for_each
logdWrite.write
logdWrite
Copy the code
- Log buffers such as main, system, and crash are maintained in logD. Logs of each module are cached in this buffer.
LogListener::onDataAvailable
LogBuffer::log
=> stats.add(elem);
maybePrune(elem->getLogId());
Copy the code
Three,Analyze the log reading process
Similarly, the process of reading logs is actually the process of the client reading messages through dev/socket/logdr. For details, please refer to the picture above.
Unlike logging, which is stored in logd in a specific format, Logcat needs to parse the log format into a string that can be seen on the command line. So there’s the processBuffer.
If logcat prints a file to a log file, if the file size is exceeded, Logcat calls the rotateLogs method to create a new file.
In Android 9.0, a log entry is stored in logD according to the following structure definition.
Four,The core logD of the log system
4.1 LogD Process Framework
Logd is the core process of the log system. It is started by init and is a deamon process residing in the background.
The main function of the process is to maintain the buffer queue of each log node and provide socket interface for reading, writing and control functions.
After the logd process starts, LogReader, LogListener, and CommandListener threads are started to process messages from the three sockets. After receiving the message, the LogBuffer class saves the log to the corresponding RAM buffer.
LogAudit is a module that receives events related to Kernel selinux and prints selinux logs in user space.
LogKlog is the module that receives kernel logs. You can read kernel logs by running the logcat command after setting the property.
LogStatistics is a LogStatistics module. The statistics is small by default. The number of printed logs can be counted only by pid/uid latitude. If logd.statistic = true is set. The system displays more latitude statistics, including pid, UID, TID, and TAG logs that have a large number of logs, helping to reduce logs.
4.2 LogD Startup Process
In logd.rc, logd is defined as a native service. When starting the service, three sockets are established to prepare for subsequent communication.
Lodw is defined as a SOCKET of type Dgram, which can be interpreted as a socket of type UDP, mainly for performance reasons: When each process writes logs, the write method is written into the buffer of the socket to return the log, and the service logic is not blocked for a long time. If the socket is TCP, the client can return only after the TCP receives an ACK response. Therefore, printing logs consumes unnecessary performance.
Here is the logD startup process:
Five,Analyze the log statistics function
What if there are too many logs? How do I find out which process is printing too many logs?
Logcat itself provides a -s parameter to count logs.
After logd.statistics = true is set, more log statistics, including pid, UID, TID, and TAG, can be displayed.
Adb shel logcat -s adb shel logcat -s adb shel logcat -s adb shel logcat -s Displays statistics stored in the LogStatistics module.
Vi.conclusion
In fact, I want to illustrate a problem that printing log actually has a lot of resource consumption, including:
1 Cross-process communication consumption: Logs are sent to logD through sockets.
2 Memory consumption: The corresponding buffer must be maintained in logD. Consumption of RAM resources;
3 CPU resource consumption: In logD, the Ring buffer often pruneLogs logs to consume CPU resources.
4 I/O consumption: On some products, logs write files in background processes or threads. This consumes a large amount of I/O consumption, which causes application or system performance problems.
Therefore, developers who read this article will want to be more thoughtful, more effective, and more reserved in their logging.