qcow2 的基本原理
qcow2 镜像格式是 QEMU 模拟器支持的一种磁盘镜像。它也是可以用一个文件的形式来表示一块固定大小的块设备磁盘。与普通的 raw 格式的镜像相比,有以下特性:
- 更小的空间占用,即使文件系统不支持空洞(holes);
- 支持写时拷贝(COW, copy-on-write),镜像文件只反映底层磁盘的变化;
- 支持快照(snapshot),镜像文件能够包含多个快照的历史;
- 可选择基于 zlib 的压缩方式
- 可以选择 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 镜像文件包含一下几部分:
- 上文中提到的头部信息
- L1 表
- refcount 表
- 一个或者多个 refcount 块
- 快照头
- L2 表
- 数据 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 位)的偏移位置:
- 从 Head 域中的 l1_table_offset 取得 L1 表的地址
- 用前(64-l2_bits-cluster_bits)位地址去索引 L1 表
- 在 L1 表中的偏移量获得 L2 表的地址
- 用地址中的接下来的 l2_bits 去索引 L2 表,获得一个 64 位的表项
- 用 L2 表中的偏移量获得 cluster 的地址
- 用地址中剩下的 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 [qiaoliyong@localhost ]$ stat test.raw
文件:"test.raw"
大小:10737418240 块:0 IO 块:4096 普通文件 [qiaoliyong@localhost ]$ 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
[qiaoliyong@localhost 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 格式不具有的功能。
参考资料
学习
- 参考https://people.gnome.org/~markmc/qcow-image-format.html 关于 qcow2 镜像格式的介绍
- 参考 http://qemu.weilnetz.de/qemu-doc.html#disk_005fimages_005fformats 关于 Qemu 使用 qcow2 的方法
- 参考 http://www.linux-kvm.org/page/qcow2 关于 qcow2 的新特性
- 参考https://fedoraproject.org/wiki/Features/KVM_qcow2_Performance qcow2 的性能
- 在 developerWorks Linux 专区寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更多参考资料。
转自: http://www.ibm.com/developerworks/cn/linux/1409_qiaoly_qemuimgages/
QEMU 使用的镜像文件:qcow2 与 raw的更多相关文章
-
(转)QEMU 使用的镜像文件:qcow2 与 raw
原文:https://www.ibm.com/developerworks/cn/linux/1409_qiaoly_qemuimgages/ qcow2 的基本原理 qcow2 镜像格式是 QEMU ...
-
qcow2、raw、vmdk等镜像格式
转自 http://www.prajnagarden.com/?p=248 http://blog.csdn.net/starshine/article/details/8179483 转者言:对pr ...
-
qcow2、raw、vmdk等镜像格式的比较和基本转换
注:本文转自http://www.cnblogs.com/feisky/archive/2012/07/03/2575167.html 云计算用一个朋友的话来说:”做云计算最苦逼的就是得时时刻刻为 ...
-
虚拟机镜像压缩(qcow2,raw)
●qcow2 格式的压缩首先,需要对虚拟机系统的剩余空间写零操作: $ dd if=/dev/zero of=/zero.dat 删除 zero.dat$ rm /zero.dat关闭虚拟机,进入虚拟 ...
-
利用Jenkins打包ISO和QCOW2镜像文件
现在的云虚拟化环境越来越多,经常会碰到需要修改并重新打包新的ISO或QCOW2镜像文件.通过手工的方式会比较麻烦,所以在镜像发布的生产环境中可以利用Jenkins来进行定期打包发布,以下介绍Jenki ...
-
KVM磁盘镜像qcow2、raw、vmdk等格式区别(转)
raw(default) the raw format is a plain binary image of the disc image, and is very portable. On file ...
-
虚拟机硬盘格式的选择:qcow2、 raw等
虚拟机硬盘格式的选择:qcow2. raw等曾经有过一段时间,徘徊于对虚拟机硬盘格式的迷惑中,2009年,终于得出了一些结论(下面的思路基本通用于其他虚拟机) 搜了下,发现大部分用qemu或者kvm的 ...
-
如何挂载一个镜像文件(how to mount an image file)
如何挂载一个镜像文件(how to mount an image file) 08/16/2012master 4 Comments 在使用KVM或Xen虚拟化的情况下,经常需要使用镜像文件(imag ...
-
[转]如何烧录tizen镜像文件?(图文教程)
http://blog.csdn.net/flydream0/article/details/9179143 上一篇文章我已讲过如何制作镜像文件(http://blog.csdn.net/flydre ...
随机推荐
-
简单三个表之间关联 与 case when语句的应用
select p.conttract_id,l.order_code,jz.cur_branch from wy_auto_workflow_log l,wg_pjhsb p,wg_jzmb jz w ...
-
11.Android之常用对话框AlertDialog学习
(1)首先我们写个简单的AlertDialog对话框,要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法,然后创建对话框可以设置对话框的属性,比如 ...
-
UVa 10870 - Recurrences
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
-
Java - Nested Classes
(本文参考:http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html) Nested Classes class OuterClas ...
-
CMDB, 配置管理数据库, ITIL - ManageEngine ServiceDesk Plus
Download Bitnami Review Board Stack click here CMDB, 配置管理数据库, ITIL - ManageEngine ServiceDesk Plus
-
ubuntu实时显示网速cpu占用和内存占用率
ubuntu实时显示网速cpu占用和内存占用率 大家在使用ubuntu的时候,有没有想让它实时显示网速,内存占用率,或者cpu占用率呢?现在我就教大家怎么实现,就像下面这样 1. 添加indicato ...
-
docker 清理容器的一些命令,彻底或选择清理
越往下的,越要慎重 列出无用的卷 docker volume ls -qf dangling=true 清理无用的卷,容器,镜像 docker volume rm $(docker volume ls ...
-
IO队列深度max_queue_depth对系统性能的影响
前段时间,发生了一个问题引起了我对IO队列深度的研究. 存储服务器中linux kernel的mpt2sas驱动模块,将max_queue_depth设置为1024时,引起系统加载驱动时卡死,而调整为 ...
-
原生AJAX请求教程
ajax 即 Asynchronous Javascript And XML,AJAX 不是一门的新的语言,而是对现有持术的综合利用.本质是在 HTTP 协议的基础上以异步的方式与服务器进行通信. 异 ...
-
[c/c++] programming之路(1)、编写程序打开记事本、计算器等
一.命令行启动程序 通过命令行关闭程序:taskkill /f /im 程序名.exe 二.打开记事本.计算器 #include <stdlib.h> void main(){ syste ...