QEMU 支持确定性记录和重放,记录在:https://github.com/qemu/qemu/blob/v2.9.0/docs/replay.txt
但是,对于完整的 Linux 内核启动,我无法让重放工作:它总是在某个时刻挂起。
这些是我正在运行的命令:
#!/usr/bin/env bash
cmd="\
time \
./buildroot/output.x86_64~/host/usr/bin/qemu-system-x86_64 \
-M pc \
-append 'root=/dev/sda console=ttyS0 nokaslr printk.time=y - lkmc_eval=\"/rand_check.out;wget -S google.com;/poweroff.out;\"' \
-kernel './buildroot/output.x86_64~/images/bzImage' \
-nographic \
\
-drive file=./buildroot/output.x86_64~/images/rootfs.ext2,if=none,id=img-direct,format=raw \
-drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \
-device ide-hd,drive=img-blkreplay \
\
-netdev user,id=net1 \
-device rtl8139,netdev=net1 \
-object filter-replay,id=replay,netdev=net1 \
"
echo "$cmd"
eval "$cmd -icount 'shift=7,rr=record,rrfile=replay.bin'"
# Different than previous.
eval "$cmd -icount 'shift=7,rr=record,rrfile=replay.bin'"
# Same as previous.
eval "$cmd -icount 'shift=7,rr=replay,rrfile=replay.bin'"
我的内核和根文件系统是用这个 Buildroot 设置生成的:https://github.com/cirosantilli/linux-kernel-module-cheat/tree/0a1a600d49d1292be82a47cfde6f0355996478f0它使用 QEMU v2.9.0。
lkmc_eval
被我的 init
脚本评估。在这里,我们打印通常是随机的用户空间内容以检查我们实际上是确定性的,然后关闭机器。
我是如何想出这些命令的:
- 从我在没有记录重放的 repo 中使用的工作命令开始
- 从 wiki 复制粘贴硬盘和网络部分:https://wiki.qemu.org/Features/record-replay
in-tree 文档说没有网络支持,但是 wiki 和 git log 说它们是从 v2.9.0 开始添加的,所以我认为文档与 wiki 相比已经过时了。
使用该设置,启动重放进行得相当远,但在消息处挂起:
[ 31.692427] NET: Registered protocol family 17
在初始记录中,下一条消息应该是:
[ 31.777326] sd 1:0:0:0: [sda] Attached SCSI disk
所以我怀疑这是 block 设备问题。
但是时间戳是相同的,所以我相信到目前为止录制和重放是有效的。
如果我只使用网络:
-net none
然后记录本身卡在:
[ 19.669685] ALSA device list:
[ 19.670756] No soundcards found.
如果有人想尝试针对它的 QEMU 补丁,只需在 /qemu/
中检查你的补丁并运行:
./build -t host-qemu-reconfigure
重建。
最佳答案
你的命令行看起来没问题,但不幸的是记录/重放是 QEMU 在这个版本中被破坏了。 我希望它能在最近几周内得到修复。
关于linux - 如何使用 QEMU 的确定性记录和重放功能进行 Linux 内核引导?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46970215/