QEMU 使用的镜像文件:qcow2 与 raw

qcow2 的基本原理

qcow2 镜像格式是 QEMU 模拟器支持的一种磁盘镜像。它也是可以用一个文件的形式来表示一块固定大小的块设备磁盘。与普通的 raw 格式的镜像相比,有以下特性:

  1. 更小的空间占用,即使文件系统不支持空洞(holes);
  2. 支持写时拷贝(COW, copy-on-write),镜像文件只反映底层磁盘的变化;
  3. 支持快照(snapshot),镜像文件能够包含多个快照的历史;
  4. 可选择基于 zlib 的压缩方式
  5. 可以选择 AES 加密

qcow2 镜像文件格式

头部信息

每一个 qcow2 文件都以一个大端(big-endian)格式的头开始,结构如下:

清单 1. qcow2 Header
 typedef struct QCowHeader {
      uint32_t magic;
      uint32_t version;

      uint64_t backing_file_offset;
      uint32_t backing_file_size;

      uint32_t cluster_bits;
      uint64_t size; /* in bytes */
      uint32_t crypt_method;

      uint32_t l1_size;
      uint64_t l1_table_offset;

      uint64_t refcount_table_offset;
      uint32_t refcount_table_clusters;

      uint32_t nb_snapshots;
      uint64_t snapshots_offset;
  } QcowHeader;

下面以一个 10G 的 qcow2 文件为例来分析各字段的含义。

清单 2. qcow2 文件的 16 进制表示
# file 1.cow2
1.cow2: QEMU QCOW Image (v2), 10737418240 bytes

0000000: 5146 49fb 0000 0002 0000 0000 0000 0000  QFI.............
0000010: 0000 0000 0000 0010 0000 0002 8000 0000  ................
0000020: 0000 0000 0000 0014 0000 0000 0003 0000  ................
0000030: 0000 0000 0001 0000 0000 0001 0000 0000  ................
0000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000060: 0000 0004 0000 0068 0000 0000 0000 0000  .......h........
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
......

前 4 个比特包含了字符 Q,F,I,然后是 0xfb,实例中的 5146 49fb 是 magic 字段。

接下来的 4 个比特包含了该镜像文件的版本号,实例中的 0000 0002 是 version 字段,代表使用的是 qcow2 版本。

backing_file_offset 占用 8 个字节,实例中 0000 0000 0000 0000,给出一个从某个文件开始偏移量。

backing_file_size 给出了一个不以 null 结尾的字符串的长度,实例中为 0000 0000。如果这个镜像文件是一个写时拷贝的,那么它是原始文件的路径。

cluster_bits,32 位(0000 0010),描述了如何映射一个镜像的地址到一个本地文件,它决定了在一个 cluster 中,偏移地址的低位是如何作为索引的。因为 L2 表占用了一个单独的 cluster 并且包含 8 字节的表项(entry),所以 cluster_bits 只有不足 3 个位,作为 L2 表的索引。

接下来的 size ,8 字节代表了该镜像文件所表示的块设备的大小,实例中为 0000 0002 8000 0000 字节,也就是 10G 的空间。

crypt_method 如果为 1 代表使用 AES 加密。

l1_size(0000 0014)和 l1_table_offset(0000 0000 0003 0000::)分别给出了 L1 表大小和偏移量。

refcount_table_offset 给出 refcount 表的偏移量(0000 0000 0001 0000)而 refcount_table_clusters 描述了以 cluster 为单位的 refcount 表的大小(0000 0001)。

nb_snapshots 给出了该镜像包含的快照数量(0000 0000), snapshots_offset 给出每个快照到 QCowSnapshotHeader 的偏移量(0000 0000 0000 0000)。

一个典型的 qcow2 镜像文件包含一下几部分:

  1. 上文中提到的头部信息
  2. L1 表
  3. refcount 表
  4. 一个或者多个 refcount 块
  5. 快照头
  6. L2 表
  7. 数据 cluster

2 级查找

在 qcow2 中,磁盘的内容是保存在 cluster 中(每个 cluster 包含一些大小为 512 字节的扇区)。为了找到给定地址所在的 cluster,我们需要查找两张表,L1->L2。L1 表保存一组到 L2 表的偏移量,L2 表保存一组到 cluster 的偏移量;

所以一个地址要根据 cluster_bits(64 位)的设置分成 3 部分,比如说 cluster_bits=12;

低 12 位是一个 4Kb cluster 的偏移(2 的 12 次方=4Kb);

接下来 9 位是包含 512 个表项目的 L2 表;

剩下 43 位的代表 L1 表偏移量。

为了获取一个给定地址(64 位)的偏移位置:

  1. 从 Head 域中的 l1_table_offset 取得 L1 表的地址
  2. 用前(64-l2_bits-cluster_bits)位地址去索引 L1 表
  3. 在 L1 表中的偏移量获得 L2 表的地址
  4. 用地址中的接下来的 l2_bits 去索引 L2 表,获得一个 64 位的表项
  5. 用 L2 表中的偏移量获得 cluster 的地址
  6. 用地址中剩下的 cluster_bits 位去索引该 cluster,获得该数据块

如果 L1 表和 L2 表中的偏移量都是空,这块区域就尚未被镜像文件分配。

注意 L1 表和 L2 表中的偏移量的前两位被保留,用做表示‘copied‘ 或‘compressed‘。

Copy-on-Write 镜像文件

qcow2 镜像可以用来保存另一个镜像文件的变化,它并不去修改原始镜像文件,只记录与原始镜像文件的不同即可,这种镜像文件就叫做 copy-on-write 镜像。虽然是一个单独的文件,但它的大部分的数据都来自原始镜像,只有跟原始镜像文件相比有变化的 cluster 才会被记录下来。

这很容易去实现,在头部信息中记录原始文件路径即可。当需要从一个 copy-on-write 镜像文件中读取一个 cluster 的时候,首先检查这块区域是否已经在该镜像文件中被分配,如果没有就从原始文件读取。

快照

快照有些类似 Copy-On-Write 文件,但区别是快照是一个可写的。快照就是原始文件本身(内部快照)。它既包含做快照之前的原始文件部分,它本身也包含可写的部分。

每一个快照都包含如下的头部结构:

清单 3. qcow2 快照 Header

  typedef struct QCowSnapshotHeader {
      /* header is 8 byte aligned */
      uint64_t l1_table_offset;

      uint32_t l1_size;
      uint16_t id_str_size;
      uint16_t name_size;

      uint32_t date_sec;
      uint32_t date_nsec;

      uint64_t vm_clock_nsec;

      uint32_t vm_state_size;
      uint32_t extra_data_size; /* for extension */
      /* extra data follows */
      /* id_str follows */
      /* name follows  */
  } QcowSnapshotHeader;

qcow2 的其他特性

qcow2 支持压缩,它允许每个簇(cluster)单独使用 zlib 压缩。它也支持使用 128 位的 AES 密钥进行加密。

创建 qcow2 和 raw 文件以及两种镜像的对比

使用 QEMU 软件包自带的 qemu-img 软件创建 qcow2 文件。

清单 4. 创建 qcow2 和 raw 文件
$ qemu-img create -f qcow2 test.qcow2 10G
Formatting ‘test.qcow2‘, fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off

$ qemu-img create -f raw test.raw 10G
Formatting ‘test.raw‘, fmt=raw size=10737418240

对比两种格式的文件的实际大小以及占用空间大小如下:

清单 5. qcow2 和 raw 文件占用空间情况对比
$ ll -sh test.*
200K -rw-r--r-- 1 qiaoliyong qiaoliyong 193K 5 月   6 10:29 test.qcow2
   0 -rw-r--r-- 1 qiaoliyong qiaoliyong  10G 5 月   6 10:28 test.raw

[[email protected] ]$ stat test.raw
  文件:"test.raw"
  大小:10737418240	块:0          IO 块:4096   普通文件

[[email protected] ]$ stat test.qcow2
  文件:"test.qcow2"
  大小:197120    	块:400        IO 块:4096   普通文件

从对比中可以看出 qcow 格式的镜像文件大小位 197120 字节,占用空间为 200K,占用了 200 块磁盘空间。而 raw 格式的文件则没有占用磁盘空间,它是一个空洞文件。

回页首

Raw 格式与 qcow2 转化

QEMU 软件包里面提供的 qemu-img 工具可用于 image 镜像一些常用操作。

将 raw 格式转化为 qcow2 格式的文件命令如下:

qemu-img convert -f raw -O qcow2 test.raw test.raw.qcow2
[[email protected] kimchi]$ ll -sh test.*
200K -rw-r--r-- 1 qiaoliyong qiaoliyong 193K 5 月   6 10:29 test.qcow2
   0 -rw-r--r-- 1 qiaoliyong qiaoliyong  10G 5 月   6 10:28 test.raw
200K -rw-r--r-- 1 qiaoliyong qiaoliyong 193K 5 月   6 10:44 test.raw.qcow2

两种格式文件的性能比较

表 1. 使用 ide 作为虚拟磁盘的驱动的三种镜像格式性能对比

cache = off writethrough writeback
Old qcow2 (0.10.5) 16:52 min 28:58 min 6:02 min
New qcow2 (0.11.0-rc1) 5:44 min 9:18 min 6:11 min
raw 5:41 min 7:24 min 6:03 min

表 2. 使用 virtio 作为虚拟磁盘的驱动的三种镜像格式性能对比

cache = off writeback
Old qcow2 (0.10.5) 31:09 min 8:00 min
New qcow2 (0.11.0-rc1) 18:35 min 8:41 min
raw 8:48 min 7:51 min

小结

本文着重介绍了 QEMU 虚拟机使用的镜像文件 qcow2 的格式以及特性,并与 raw 格式镜像做了对比。qcow2 格式的文件虽然在性能上比rRaw 格式的有一些损失(主要体现在对于文件增量上,qcow2 格式的文件为了分配 cluster 多花费了一些时间),但是 qcow2 格式的镜像比 Raw 格式文件更小,只有在虚拟机实际占用了磁盘空间时,其文件才会增长,能方便的减少迁移花费的流量,更适用于云计算系统,同时,它还具有加密,压缩,以及快照等 raw 格式不具有的功能。

参考资料

学习

转自: http://www.ibm.com/developerworks/cn/linux/1409_qiaoly_qemuimgages/

时间: 2025-01-10 04:27:30

QEMU 使用的镜像文件:qcow2 与 raw的相关文章

qcow2、raw、vmdk等镜像格式的比较和基本转换

注:本文转自http://www.cnblogs.com/feisky/archive/2012/07/03/2575167.html 云计算用一个朋友的话来说:”做云计算最苦逼的就是得时时刻刻为一些可能一辈子都碰不到的事做 好准备.更苦逼的就是刚以为一个问题不会遇到,立刻就发生了...“.这个还真的没有办法, 谁让哥我是搞云计算的呢,简单一个虚拟化就搞的你蛋疼,你还能想其它的吗?一直纠结在做虚 拟化使用什么镜像格式,刚刚开始用了raw的file,后来发现LVM的很多特性对于虚拟化还是有比较 理

qcow2、raw、vmdk等镜像格式

目前主要有那些格式来作为虚拟机的镜像:raw(default) the raw format is a plain binary image of the disc image, and is very portable. On filesystems that support sparse files, images in this format only use the space actually used by the data recorded in them.老牌的格式了,用一个字来

[转载]如何挂载qcow2格式的镜像文件(how to mount a qcow2 image)

两个月前,写了一篇“如何挂载一个镜像文件”,当时没有把qcow2的挂载方法写进入,刚好一个博友留言提到qcow2了,就再一小篇关于mount qcow2格式的客户机镜像吧.QCOW2是目前QEMU(qemu-kvm)推荐使用的guest镜像文件格式,在KVM.Xen虚拟化中的使用都是比较广泛的.可以使用qemu自带的一个工具qemu-nbd来挂载一个客户机,具体步骤如下:(qemu-nbd 在普通的QEMU编译和安装后也会得到qemu-nbd工具,在Fedora中好像在“qemu-common”

如何挂载一个镜像文件(how to mount an image file)

如何挂载一个镜像文件(how to mount an image file) 08/16/2012master 4 Comments 在使用KVM或Xen虚拟化的情况下,经常需要使用镜像文件(image file),我们可以将Guest系统启动起来,然后对镜像文件进行修改,不过这样有时也是比较麻烦,其实也是可以将镜像文件直接进行mount的,可以用如下两种办法. (本文写的RAW格式镜像文件的挂载:我的另一篇文章写了"如何挂载qcow2格式的镜像文件") 方法一:找出分区开始的开始位置

虚拟机硬盘格式的选择:qcow2、 raw等

虚拟机硬盘格式的选择:qcow2. raw等曾经有过一段时间,徘徊于对虚拟机硬盘格式的迷惑中,2009年,终于得出了一些结论(下面的思路基本通用于其他虚拟机) 搜了下,发现大部分用qemu或者kvm的,都默认使用qcow2来作为虚拟硬盘,但qemu官方默认是用raw.下面是qemu wiki对两种格式的描述:rawRaw disk image format (default). This format has the advantage of being simple and easily ex

创建文件系统镜像文件

在这里,我们想建立一个2G左右大小(可以按需设定)的镜像文件,包含三个分区:第一个分区是 b, fat32分区,大小256M,用来存储内核文件,设备树文件,uboot使用的启动脚本文件,配置FPGA的rbf文件等:第三个分区是 a2, raw分区,放在镜像文件的末端,大小 2MiB,用来存放 preloader 和 uboot 的代码,主引导记录引导系统,根据需要 uboot 也可以在 fat32 分区中保存为镜像文件 u-boot.img:第二个分区占用了所有剩下的所有空间,用作 Linux

Android系统的镜像文件的打包过程

在前面一篇文章中,我们分析了Android模块的编译过程.当Android系统的所有模块都编译好之后,我们就可以对编译出来的模块文件进行打包了.打包结果是获得一系列的镜像文件,例如system.img.boot.img.ramdisk.img.userdata.img和recovery.img等.这些镜像文件最终可以烧录到手机上运行.在本文中,我们就详细分析Android系统的镜像文件的打包过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! <Andr

从零开始构建一个centos+jdk7+tomcat7的docker镜像文件

从零开始构建一个centos+jdk7+tomcat7的镜像文件 centos7系统下docker运行环境的搭建 准备centos基础镜像 docker pull centos 或者直接下载我准备好的镜像 docker pull registry.cn-hangzhou.aliyuncs.com/repos_zyl/centos:0.0.1 准备jdk7和tomcat7安装包 创建工作目录, mkdir -p /z/docker 准备下载jdk7的tar.gz包http://download.o

Android系统定制——Download Android System 及加载system镜像文件

定制android系统(配置及相关系统的镜像文件),具体可参考:Driver_All_in_One_V1.0--MT6735_6753.pdf文档,特别需要理解的是Download部分. 与之对应的软件是:Smart Phone Flash Tool,一般是在菜单栏的Download部分进行选择操作. Download-agent(下载代理):选择 \升级固件与升级固件的工具\SP_Flash_Tool_exe_Windows_v5.1536.00.000 文件(通常不用特别选择,使用默认的即可