VMStateDescription

在迁移的最后阶段,对每个SaveStateEntry的vmsd会跳用函数vmstate_save。在上一节中,我们跳过了这部分的讲解,在这节中我们补上。

VMStateDescription是SaveStateEntry的一部分

VMStateDescription并不是单独存在,而是SaveStateEntry的一部分。但是并非所有的SaveStateEntry结构都有vmsd。比如上一小节看到的“ram”,”block“这几个SaveStateEntry就没有。

正因为如此,vmsd的出现会伴随这SaveStateEntry。通畅我们见到创建两者的函数是vmstate_register_with_alias_id。比如在函数apic_common_realize中,每个apic设备就会有一个SaveStateEntry且它的vmsd就是vmstate_apic_common。

发送流程 vmstate_save

接下来我们了解一下上一小节中我们略过的函数。

     vmstate_save(f, se, vmdesc)
         if (!se->vmsd) {
             vmstate_save_old_style(f, se, vmdesc);

         vmstate_save_state(f, se->vmsd, se->opaque, vmdesc)
             vmsd->pre_save(se->opaque)

             ; iterate on fields
             ; iterate on elements of this field
             vmsd_desc_field_start
             vmstate_save_state(f, field->vmsd, curr_elem, vmdesc_loop)
             vmstate_save_state_v(f, field->vmsd, curr_elem, vmdesc_loop, field->struct_version_id)
             field->info->put(f, curr_elem, size, field, vmdesc_loop)
             vmsd_desc_field_end

             ; go into subsection
             vmstate_subsection_save()
                 vmstate_save_state(f, vmsdsub, se->opaque, vmdesc)

             vmsd->post_save(se->opaque)

当然这个调用图中我们跳过了没有vmsd的情况。先着重观察有vmsd时的操作。

其实上面的结构不是很清楚,让我再多说两句:

  • vmsd有多个field

  • field有多个element

  • field类型可以嵌套

接收流程 vmstate_load

这个函数是vmstate_save的另一半。

可谓是珠联璧合。

结构体

是时候展示一下结构体的庐山真面目了。

是不是很长,感觉一头雾水? 我也觉得是,那就再来一张凸显其中某些关联的图。

这样希望能够突出几点:

  • vmsd包含了fields的数组,每个元素都是VMStateField结构

  • 每个field又包含了多个elements,其个数由num/num_offset决定,其大小由size/size_offset决定

  • elements的起始位置由offset决定,在opaque指针指向的空间

如何定义

对结构体有了大致了概念后,我们就可以来看看代码中我们是如何定义的。下面这个是apic设备的vmsd。

可以看到,它的fields上有多个部分,而且还包含了一个subsection。其他的成员都一眼看穿,唯独fields成员的定义隐藏在VMSTATE_宏定义里。那就让我们打开这个宏定义看看吧。

VMSTATE_UINT8

VMSTATE_UINT32_ARRAY

Last updated

Was this helpful?