QEMU 增加自定义日志逻辑
使用 -d my_log
过滤 LOG_MY_LOG
日志的底层机制
核心逻辑
QEMU 通过 名称映射 和 位掩码匹配 实现 -d my_log
参数与 LOG_MY_LOG
日志的关联。具体流程如下:
一、名称与位掩码的绑定
-
定义日志类别
在include/qemu/log.h
中声明自定义日志的 位掩码:// 假设已预留第 20 位(需确保不与 QEMU 内置项冲突) #define LOG_MY_LOG (1 << 20)
-
注册名称映射
在util/log.c
的qemu_log_items[]
数组中添加条目,将字符串"my_log"
绑定到LOG_MY_LOG
:const QEMULogItem qemu_log_items[] = { // ... 其他内置日志项 { "my_log", LOG_MY_LOG }, // 关键绑定步骤 { NULL, 0 } };
- 底层行为:QEMU 解析
-d my_log
时,会遍历此数组,将"my_log"
翻译为LOG_MY_LOG
的位掩码。
- 底层行为:QEMU 解析
二、运行时过滤流程
-
命令行解析
当启动 QEMU 时:qemu-system-x86_64 -d my_log,mmu -D /tmp/qemu.log
- QEMU 将
my_log
和mmu
转换为对应的位掩码(LOG_MY_LOG | LOG_MMU
)。
- QEMU 将
-
日志输出条件检查
在代码中调用qemu_log_mask()
时:qemu_log_mask(LOG_MY_LOG, "Custom log: value=%d\n", value);
- 底层行为:检查
LOG_MY_LOG
的位掩码是否在全局日志掩码(qemu_loglevel
)中被启用。若匹配,则输出日志。
- 底层行为:检查
三、常见问题与验证方法
1. 日志未输出
-
原因 1:
qemu_log_items[]
中未注册my_log
名称。
验证:运行qemu-system-x86_64 -d help
,检查输出列表中是否包含my_log
。 -
原因 2:位掩码冲突。
验证:确保LOG_MY_LOG
的位掩码(如1<<20
)未被 QEMU 内置日志项占用。
2. 性能问题
- 高频日志优化:若日志频率过高(如循环中调用),可添加静态条件限制:
static bool log_enabled; if (unlikely(log_enabled)) { qemu_log_mask(LOG_MY_LOG, "..."); }
四、完整代码示例
1. 注册日志名称(util/log.c
)
// 在 qemu_log_items[] 数组中添加:
{ "my_log", LOG_MY_LOG },
2. 定义掩码(include/qemu/log.h
)
// 确保位掩码唯一
#define LOG_MY_LOG (1 << 20)
3. 触发日志(任意源码文件)
qemu_log_mask(LOG_MY_LOG, "Memory allocated at %p\n", ptr);
4. 运行验证
qemu-system-x86_64 -d my_log -D qemu.log
# 检查 qemu.log 中是否包含 "Memory allocated at ..."
五、调试技巧
-
查看所有可用日志项:
qemu-system-x86_64 -d help
输出中应包含
my_log
项。 -
动态启用日志:
通过环境变量在运行时临时启用:QEMU_LOG="my_log" qemu-system-x86_64 ...
六、总结
通过 -d my_log
过滤自定义日志的关键是:
- 名称与位掩码的绑定(在
qemu_log_items[]
中注册) - 位掩码唯一性(避免与内置日志冲突)
- 正确调用
qemu_log_mask()
(条件匹配)