整体架构
现在就让我们来看看迁移这件事的总体架构吧。
发送端
从migrate命令开始
通过上一小节的例子,我们可以看到迁移可以通过在monitor中执行命令开始。既然如此,那我们就从这里开始。
话说要讲清楚monitor中命令执行的机制,还真是要花费一些事件。通过一些学习,发现迁移的入口函数是hmp_migrate。下面就是本人总结的从hmp_migrate开始到迁移主函数的流程。
hmp_migrate(), invoked from handle_hmp_command()
qmp_migrate()
migrate_get_current(), global MigrationState
migrate_prepare()
migrate_init()
tcp_start_outgoing_migration()
socket_start_outgoing_migration()
unix_start_outgoing_migration()
socket_start_outgoing_migration()
socket_outgoing_migration
migration_channel_connect(s, sioc, hostname, err)
exec_start_outgoing_migration()
migration_channel_connect(s, ioc, NULL, NULL)
fd_start_outgoing_migration()
migration_channel_connect(s, ioc, NULL, NULL)
migrate_fd_connect(s, NULL)
rdma_start_outgoing_migration()
migrate_fd_connect(s, NULL)
migration_thread()可以看到,迁移的接口有
tcp
unix
exec
fd
rdma
但是万变不离其宗,最后都启动了migration_thread这个线程处理。
迁移主函数 migration_thread
所以最关键的就是这个迁移的主函数migration_thread。那我们把这个函数也打开。
虽然这个函数很长,不过整体的结构还算清晰。大致可以分成这么几个阶段:
发送header
建立迁移的准备
迭代传输
完成迁移
其中主要就是通过几个不同的se->ops来实现的。
接收端
从incoming开始
接收端在运行时需要加上-incoming选项,所以我们也从incoming开始。
看着要比发送端麻烦些,不过还好找到了各种方式最终都执行到qemu_loadvm_state()。
qemu_loadvm_state
接收的过程相对发送要“简单”,主要的工作都隐藏在了section的三种情况中。
QEMU_VM_SECTION_START | QEMU_VM_SECTION_FULL
QEMU_VM_SECTION_PART | QEMU_VM_SECTION_END
QEMU_VM_COMMAND
第一种代表了setup阶段和最后vmstate_save阶段。 第二种代表了iteration的中间阶段和最后一次完成。 第三种还没有仔细看。
但是至少从前两种情况看,大家都走到了vmstate_load。不错。
SaveStateEntry
迁移过程中起到关键作用的数据结构名字是SaveStateEntry,也就是代码中的se。
所有的SaveStateEntry结构都链接在全局链表savevm_state上。上图列举了几个比较重要的SaveStateEntry。比如名字叫ram的就是管理RAMBlock的。而且有意思的是,这几个的vmsd都是空。
隐藏的重点
在上述migrate_thread的流程中,有一个隐藏的函数vmstate_save。如果你把这个函数打开,那又将是一番新的天地。今天就先到这里把。
Last updated
Was this helpful?