qemu系统的trace使用

本文介绍QEMU的编译配置、日志记录方式及自定义追踪事件的添加过程。涵盖编译参数说明、日志输出路径配置、追踪事件原理分析,以及如何在QEMU中添加自定义追踪事件并进行热迁移测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                       

首席安全官+是一个聚焦“云计算、大数据、人工智能”等高技术领域,致力网络空间安全发展与战略研究,发布网络安全创新理念、先进架构、前沿技术、产业趋势和资本动态的平台,努力打造“有特色、高水平、国际化”的网络安全思想高地。

                                                                                          微信二维码

                                       

目录

1. 重新编译qemu

2. 日志记录方式

2.1. 默认效果

2.2. 分析代码

2.3.查看到日志文件中打印

2.4.对接libvirt

3. 添加自定义trace-event


1. 重新编译qemu

[root@localhost qemu-2.8.0]# ./configure  --target-list=x86_64-softmmu --enable-kvm --prefix=/usr --enable-debug --enable-numa --enable-trace-backends=simple

[root@localhost qemu-2.8.0]#  make

编译参数–enable-trace-backends可以指定trace系统使用的后端系统(backend),如果指定为log,这样trace函数如下:

                           

                                                                                                 图1-1
如果后端为simple(默认值),则trace函数为:

                                

                               

                                                                                                   图1-2
各种不同的trace方式的详细解释可以参考qemu文档:./qemu-5.0.0/docs/devel/tracing.txt
 

2. 日志记录方式

2.1. 默认效果

打开某个event的开关,然后进行操作,默认可以打印在qemu monitor上:

(qemu) trace-event migration_thread_setup_complete on
(qemu) migrate -d tcp:0:4444
(qemu)
(qemu)
(qemu)
(qemu) 39288@1545806882.716352:migration_thread_setup_complete

2.2. 分析代码

qemu_logfile
$1 = 0x7fddf6411450 "%d@%zd.%06zd:migration_thread_setup_complete \n"
(gdb) p qemu_logfile
$2 = (FILE *) 0x7fddeff521c0 <_IO_2_1_stderr_>

可以看到默认打印在标准输出stderr上.

qemu_logfile = fopen(logfilename, log_append ? “a” : “w”);

                               

                                                                                      图2-1 设置logfile
这里没有设置logfilename,因此qemu_logfile = stderr,所以
#全局搜索logfilename,得到,但是打断点之后发现并没有走这里,因此继续跟踪该函数调用情况。

                               

                                                                                      图2-2
全局搜索qemu_set_log_filename

                                

                                                                                                      图2-3

trace_init_file函数会被调用,并且file为空,因此qemu_set_log_filename才没有执行,继续跟踪调用栈
vl.c:4129 trace_init_file(trace_file);

                               

                                                                                              图2-4

然后发现不是这里,这里是backend为其他选项的时候的处理,log应该是另外一个地方也调用了qemu_set_log_filename,是下面vl.c:4134处

if (log_file) {
        qemu_set_log_filename(log_file, &error_fatal);
    }

                                  

                                                                                          图2-5
搜索QEMU_OPTION_D

DEF("D", HAS_ARG, QEMU_OPTION_D, \
"-D logfile      output log to logfile (default stderr)\n",

使用方式应该是-D /var/log/qemu/qemu.log

2.3.查看到日志文件中打印

[root@localhost ~]# cat /var/log/qemu/qemu.log
8105@1546410490.874924:migration_thread_setup_complete

2.4.对接libvirt

xml中使用qemu:commandline配置log文件路径

[root@localhost mydisk1]# cat vm1.xml
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>vm1</name>
  <memory unit='M'>2048</memory>
  <metadata>
    <app1:foo xmlns:app1="http://app1.org/app1/">..</app1:foo>
    <app2:bar xmlns:app2="http://app1.org/app2/">..</app2:bar>
  </metadata>
  <qemu:commandline>
                <qemu:arg value='-D'/>
                <qemu:arg value='/var/log/qemu/qemu.log'/>
  </qemu:commandline>
.....
</domain>
[root@localhost mydisk1]# virsh start vm1
error: Failed to start domain vm1
error: internal error: process exited while connecting to monitor: /var/log/qemu/qemu.log: Permission denied

解决方法:关闭selinux

查看进程

[root@localhost mydisk1]# ps -ef|grep qemu
root       899     1  0 Jan03 ?        00:00:00 /usr/bin/qemu-ga --method=virtio-serial --path=/dev/virtio-ports/org.qemu.guest_agent.0 --blacklist=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status -F/etc/qemu-ga/fsfreeze-hook
root     21360     1 28 16:31 ?        00:00:01 /usr/bin/qemu-system-x86_64 -name guest=vm1,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-7-vm1/master-key.aes -machine pc-i440fx-2.6,accel=kvm,usb=off -cpu Broadwell,+vme,+ss,+ht,+vmx,+osxsave,+f16c,+rdrand,+hypervisor,+arat,+tsc_adjust,+xsaveopt,+pdpe1gb,+abm -m 2048 -realtime mlock=off -smp 2,sockets=1,cores=2,threads=1 -uuid 36a5008d-2da8-4790-955b-57fc1f32c376 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-7-vm1/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=localtime -no-shutdown -boot order=c,menu=on,strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x4 -drive file=/home/mydisk1/ubuntu-14.04-server.qcow2,format=qcow2,if=none,id=drive-ide0-0-0 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -netdev tap,fd=24,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=00:02:02:00:a0:04,bus=pci.0,addr=0x3 -chardev socket,id=charserial0,host=0.0.0.0,port=4003,telnet,server,nowait -device isa-serial,chardev=charserial0,id=serial0 -chardev socket,id=charchannel0,path=/var/lib/libvirt/qemu/test.agent,server,nowait -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0 -vnc 0.0.0.0:0 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -D /var/log/qemu/qemu.log -msg timestamp=on
root     21388 20174  0 16:32 pts/1    00:00:00 grep --color=auto qemu

通过virsh打开trace-event

[root@localhost ~]# virsh qemu-monitor-command  vm1 --hmp "trace-event migration_thread_setup_complete on"

#列出已经打开的trace-event

[root@localhost ~]# virsh qemu-monitor-command  vm1 --hmp "info trace-events"

3. 添加自定义trace-event

qemu目录下每个子系统都有一个trace-events文件,里面申明了很多静态的trace events

[root@localhost qemu-2.8.0]# ll */trace-events
-rw-r--r--. 1 user user   822 Dec 21  2016 audio/trace-events
-rw-r--r--. 1 user user  8024 Dec 21  2016 block/trace-events
-rw-r--r--. 1 user user  1655 Dec 21  2016 crypto/trace-events
-rw-r--r--. 1 user user  4083 Dec 21  2016 io/trace-events
-rw-r--r--. 1 user user   834 Dec 21  2016 linux-user/trace-events
-rw-r--r--. 1 user user 13764 Dec 21  2016 migration/trace-events
-rw-r--r--. 1 user user  1323 Dec 21  2016 net/trace-events
-rw-r--r--. 1 user user  2032 Dec 21  2016 qapi/trace-events
-rw-r--r--. 1 user user   333 Dec 21  2016 qom/trace-events
-rw-r--r--. 1 user user   693 Dec 21  2016 target-arm/trace-events
-rw-r--r--. 1 user user   352 Dec 21  2016 target-i386/trace-events
-rw-r--r--. 1 user user   252 Dec 21  2016 target-ppc/trace-events
-rw-r--r--. 1 user user  1133 Dec 21  2016 target-s390x/trace-events
-rw-r--r--. 1 user user  2079 Dec 21  2016 target-sparc/trace-events
-rw-r--r--. 1 user user  3004 Dec 21  2016 ui/trace-events
-rw-r--r--. 1 user user  1697 Dec 21  2016 util/trace-events

这里用migration/trace-events做实验

[root@localhost qemu-2.8.0]# cat migration/trace-events |grep migration_thread_
migration_thread_after_loop(void) ""
migration_thread_file_err(void) ""
migration_thread_setup_complete(void) ""
migration_thread_huangxun(void) ""
migration_thread_low_pending(uint64_t pending) "%" PRIu64

仿照migration_thread_setup_complete写一个migration_thread_huangxun,
括号里面是参数,“”是格式,可以参考qemu源码主目录下的trace-events文件的讲解,添加完成后,重新编译qemu
查看新生成的代码

[root@localhost qemu-2.8.0]# grep -l -r 'huangxun'
qemu-img
trace/generated-tracers.o
trace/generated-tracers.h
trace/generated-tracers.h-timestamp
trace/generated-tracers.c
trace/generated-tracers.c-timestamp
qemu-io
migration/trace-events
i386-softmmu/qemu-system-i386
ivshmem-server
qemu-nbd
libqemuutil.a
trace-events-all
qemu-ga
x86_64-softmmu/qemu-system-x86_64
fsdev/virtfs-proxy-helper

#[root@localhost qemu-2.8.0]# cat trace/generated-tracers.h|less
static inline void trace_migration_thread_huangxun(void)
{
    if (true) {
        if (trace_event_get_state(TRACE_MIGRATION_THREAD_HUANGXUN)) {
            struct timeval _now;
            gettimeofday(&_now, NULL);
            qemu_log_mask(LOG_TRACE, "%d@%zd.%06zd:migration_thread_huangxun " "" "\n",
                          getpid(),
                          (size_t)_now.tv_sec, (size_t)_now.tv_usec
                          );
        }
    }
}
#[root@localhost qemu-2.8.0]# cat trace/generated-tracers.c|less
TraceEvent _TRACE_MIGRATION_THREAD_HUANGXUN_EVENT = {
    .id = 0,
    .vcpu_id = TRACE_VCPU_EVENT_NONE,
    .name = "migration_thread_huangxun",
    .sstate = TRACE_MIGRATION_THREAD_HUANGXUN_ENABLED,
    .dstate = &_TRACE_MIGRATION_THREAD_HUANGXUN_DSTATE
};
[root@localhost qemu-2.8.0]# cat trace-events-all|less
migration_thread_after_loop(void) ""
migration_thread_file_err(void) ""
migration_thread_setup_complete(void) ""
migration_thread_huangxun(void) ""

使用新增加的event

[root@localhost qemu-2.8.0]# vim migration/migration.c

                                   

                                                                                           图3-1

进行热迁移测试

源端启动参数

/usr/bin/qemu-system-x86_64 -m 256 -cpu host -drive file=/home/mydisk1/ubuntu-14.04-server.qcow2 -smp 2  -enable-kvm  -net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap0,script=no,downscript=no -serial telnet:0.0.0.0:4000,server,nowait -nographic  -vnc 0:0 -D /var/log/qemu/qemu.log

目的端启动参数

/usr/bin/qemu-system-x86_64 -m 256 -cpu host -drive file=/home/mydisk1/ubuntu-14.04-server.qcow2 -smp 2  -enable-kvm  -net nic,model=virtio,macaddr=00:00:00:00:00:01 -net tap,ifname=tap1,script=no,downscript=no -serial telnet:0.0.0.0:4001,server,nowait -nographic -incoming tcp:0:4444 -vnc 0:1 -D /var/log/qemu/qemu2.log

打开event开关,并进行迁移操作

(qemu) trace-event migration_thread_huangxun on
(qemu) migrate -d tcp:0:4444

查看log,成功打印event信息

[root@localhost ~]# cat /var/log/qemu/qemu.log
13096@1546839795.152836:migration_thread_huangxun

Reference

[1]QEMU 与块设备
http://docs.ceph.org.cn/rbd/qemu-rbd/
[2]qemu monitor protocol简介
https://blog.youkuaiyun.com/fulaidai/article/details/23714561
错误处理

使用 QEMU 安装操作系统后运行时出现闪退问题,可能涉及多个层面的原因,包括硬件兼容性、配置参数错误、镜像损坏或系统调用未正常结束等。以下是一些常见的解决方法和排查思路: ### 3.1 检查 QEMU 的退出方式 有时 QEMU 并未正常退出,而是由于某些操作中断导致强制关闭。在这种情况下,建议通过组合键 **Ctrl + A** 松开后再按 **X** 来正常退出 QEMU 进程[^2]。如果 QEMU 是通过脚本(如 `make qemu`)启动的,确保该脚本执行完成或以正确方式终止。 ### 3.2 验证镜像文件完整性 QEMU 启动失败可能是由于使用的磁盘镜像文件损坏或格式不兼容所致。可以尝试以下操作: - 使用 `qemu-img check <image_file>` 命令检查镜像文件是否完整。 - 重新生成镜像文件,例如使用 `qemu-img create -f qcow2 disk.img 2G` 创建新的虚拟磁盘。 - 确保引导介质(ISO 或内核镜像)路径正确且可访问。 ### 3.3 调整 QEMU 启动参数 某些硬件设备或图形设置可能导致窗口异常关闭。可以通过修改 QEMU 的命令行参数进行调试: - 添加 `-nographic` 参数禁用图形界面,转而使用串口控制台进行调试: ```bash qemu-system-x86_64 -nographic -kernel your_kernel_image ``` - 使用 `-serial stdio` 将串口输出重定向到标准输入输出,便于查看日志信息。 - 若使用的是 xv6 或类似教学操作系统,可参考其 Makefile 中的标准 QEMU 启动命令,确保参数一致。 ### 3.4 检查操作系统引导过程 若系统无法进入 `main()` 函数或在早期阶段崩溃,可能与引导加载程序(Bootloader)或内核初始化有关。可以在源码中插入调试输出(如 `printf` 或串口打印),确认执行流程是否卡在特定位置。 ### 3.5 硬件兼容性与驱动问题 不同主机上的硬件环境可能存在差异,尤其是在台式机上运行时,某些默认配置可能不兼容。可以尝试: - 更换 CPU 类型,如添加 `-cpu qemu64` 或 `-cpu core2duo` 参数。 - 禁用不必要的设备模拟,减少潜在冲突。 - 在 BIOS/UEFI 设置中启用虚拟化支持(VT-x/AMD-V),并确认 KVM 是否可用。 ### 3.6 日志与调试工具 开启 QEMU 的调试输出有助于定位问题: - 添加 `-d help` 查看支持的日志类型。 - 使用 `-d trace:vmsec_start` 等选项追踪特定事件。 - 结合 GDB 调试器附加到 QEMU 实例,逐步执行代码并查看堆栈状态。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值