Page 485 - 《软件学报》2024年第4期
P. 485
吴圣垚 等: HiLog: OpenHarmony 的高性能日志系统 2063
统内核日志缓冲区 (kernel_log_buffer) 作为 HiLog 的缓冲区, 适用日志流量较小的场景, 对于设备的内存需求量极
小, 其硬件约束条件为 OpenHarmony 硬件标准的 L1 设备 (即内存介于 128 KB–128 MB 之间的设备).
3.3.2 HiLog 日志系统 IPC
图 5(a) 描绘了标准 HiLog 进程间通信模型. 一方面各个不同进程产生的日志需要通过 IPC 收集到 hilogd 进
程, 另一方面读日志进程又需要通过向 hilogd 进程请求日志数据, 因此日志系统的 IPC 效率对日志吞吐量存在重
要影响. 标准 HiLog 采用套接字 (Socket) 作为 IPC 实现方案, 在写入阶段构造 socket_input 客户端/服务端; 在输出
阶段构造 socket_output 客户端/服务端.
IPC 模型 IPC 模型
libhilog libhilog
libhilog
日志生成 日志生成
hilogd
日志生成
socket_input socket_input socket_input
客户端 服务端 客户端
ioctl
hilog_buffer
kernel_log_buffer
hilogtool hilogtool
socket_ socket_
socket_output output output socket_output ioctl
客户端 客户端
服务端 服务端 hilogtool
日志输出 日志输出 日志输出
(a) 标准 HiLog (b) 轻量 HiLog
图 5 HiLog 日志系统的进程间通信模型
socket_input 服务端采用多路 IO 复用模型 (IO multiplexing) 构建. 由于一般情况下, 系统中会存在多个系统进
程和第三方应用进程, 因此服务端需要同时应对多个客户端, 日志的写入存在并发特征; 同时, 每个进程在每个时
间段产生的日志数量是不定的, 且每一条日志的长度 (字节数) 也是不等的, 因此日志的写入数据量存在时间分布
不均匀特征. 此时如果采用多线程策略, 对于每一个客户端都使用独立线程进行处理无疑是资源消耗的. 基于以上
情景, 综合考虑性能和系统资源消耗, 采用多路 IO 复用模型构建 socket_input 服务端, 使服务端同时监听所有客
户端的文件描述符, 一旦有客户端就绪就进行日志的接收, IO 复用使连接在服务端和多个客户端之间流转, 适用
于数据的收发时间不定、收发量不均的情况.
socket_input 客户端采用非阻塞 IO 模型 (non-blocking input/output) 构建. 由于 socket_input 服务端采用单线
程的多路 IO 复用模型构建, 因此不能保证对每个客户端日志的实时接收, 如果此时客户端采用同步调用方式会导
致进程阻塞 (服务端在完成数据接受前不会相应其他客户端的请求), 造成性能的下降并影响后续日志的写入. 因
此 libhilog 的客户端采用异步调用方式构建, 即不论服务端是否接收完成, 都持续发送后续日志.
socket_output 客户端/服务端均采用阻塞 IO (blocking input/output) 模型构建. 由于读日志事件的数据量较大
且需要确保数据到达的先后顺序, 且从需求分析不会同时存在太多读日志进程, 因此阻塞 IO 不会给系统带来过大
的负担. 因此在输出阶段, 每个读日志进程加载 hilogtool, 维护各自的 socket_output 客户端向 hilogd 发送读日志请
求, hilogd 对于每一个客户端创建一个线程操作 socket_output 服务端.
轻量 HiLog 的 IPC 模型如图 5(b) 所示, 受计算资源的限制, 在用户态维护一个系统守护进程用于日志收发和
存储是奢侈的, 因此面向 L1 的 HiLog 日志系统的用户态和内核态日志都将写入内核态的 kernel_log_buffer 中, 读