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?