本人目前就职于烽火集成,从事云计算产品架构设计相关工作,长期专注于内核、虚拟化、分布式、云计算等方向。
技术交流请联系:xiaoding@fiberhome.com
在libvirt 使用save命令对虚拟机进行存储后,将libvirt的信息,虚拟机的内存,cpu以及其他设备的信息都存储了起来。
先把文件格式大致的画出来。
这里就对这一文件进行分析。
首先将存储文件的2进制信息发出来。
这是存储文件中的一部分信息,结合代码来看一下这个文件究竟是什么
首先,文件最开始存储了_virQEMUSaveHeader 文件的头信息。
头信息总共占用了0x5b个字节。
忽略libvirt存储配置的一部分,然后直接到达qemu开始存储文件的位置。
根据上面头文件信息,可以得知,qemu存储文件的起始位置为0x1207+0x5b=0x1262
可以看到从0x1263开始就是qemu存储的文件了。接下来就分析qemu存储文件格式。
这是存储qemu虚拟机状态的函数,这里可以看按到大致流程
首先是qemu中的魔数(4字节),qemu文件版本(4字节),
然后就是需要save的设备的信息,首先是section start的标记(1字节)
然后是section_id。(4字节)设备名字长度1字节,设备名字,然后实例id(4字节)(版本id)4字节
0x127b开始,就是ram的save函数进行记录的信息。
首先是存储了8字节 ram总共占用了多少字节 这里是0x808d1004。这里除了guest的内存还有其他设备的寄存器也在这里保存。
接下来是pc.ram 内存,我们的虚拟机使用了2G内存,使用了0x80000000。
vga.vram 显卡的显存 8M 使用了0x800000
pc.bios bios寄存器 256k 0x40000
virtio-net-pci寄存器 256k 0x40000
acpi表 128k 0x20000
cirrus_vga显存 64k 0x010000
acpi的table-loader 4k 0x1000
存储结尾标记 RAM_SAVE_FLAG_EOS
这里到达0x1351结束,接下来就是要存储的设备进行一一存储了。
记录了设备的其实信息后,就会调用设备自身来进行数据存储到达0x1356
在ram_find_and_save_block中 进行了实际的存储。
ram_save_page 继续执行存储page
这里来看一下如何存储页面偏移。
这样就可以看到 0x1356后接下来是存储8个字节page的标记位
0x00000008 就是offset=0 cont=0 flag=RAM_SAVE_FLAG_PAGE,因为是第一次,所以存储了
设备的名字。
从0x1366开始就是存储4k的页面,
在ram_find_and_save_block中 会循环执行ram_save_page函数,直到全部存储完所有内存。
因此存储模式就是 页偏移+页内容
所以接下来直接查看0x2366的信息。
可以看到第二个页的标记是0x1022,
由于第二个页面是全0页,所以做了压缩处理。第二个页offset=0x10000,cont=0x20,flag=RAM_SAVE_FLAG_COMPRESS。
然后存入1字节0
紧接着0x236e是第三个页面是0x2022 后面的就不过多说明了。
pc.ram 是2G,当pc.ram存储完后,会接着存储其他设备。
可以看到从0x00939cb开始就是存储vag.ram的信息。由于第一个页就是0页。值是0x00000002.
所以标记offset=0,cont=0,flag=RAM_SAVE_FLAG_COMPRESS。由于第一次存储该设备,所以存入设备名字。
当这些设备全部存储完毕后,就是存储结尾。
这里从最后一个 设备开始查找,最后一个设备占用4k,所以从0x00a72d6d开始向后4k来查找。
从0x00a73d6e开始设备信息查找完成,然后存入ram结束信息RAM_SAVE_FLAG_EOS 8字节 0x00000010 。
从0x00a73d77开始 ,就是进行最后一次存储,此时会存储cpu信息。
0x00a73d78 是03 是标记存储结束。sectionid是 0x00000002。然后存入表示RAM_SAVE_FLAG_EOS 8字节0x00000010
从 0x00a73d83开始 存储QEMU_VM_SECTION_FULL 1字节 0x04 然后sectionid 0x00000000
然后是设备的名字,设备instance_id和version_id。然后使用vmstate_save来存储信息。
从0x00a73d89开始是timer设备的信息。
timer设备的state有3个VMSTATE_INT64组成,即24字节。
从00a73d97到00a73dae用存储timer的state信息。
所以对于有状态设备来说,就在这里就进行存储。
后面的设备就不一一分析。
当存储完成后,存入QEMU_VM_EOF。