整体架构

现在就让我们来看看迁移这件事的总体架构吧。

发送端

从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?