歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> QEMU 使用的鏡像文件:qcow2 與 raw

QEMU 使用的鏡像文件:qcow2 與 raw

日期:2017/2/28 14:25:03   编辑:Linux教程

本文介紹了 qcow2 和 raw,它們都是 QEMU(KVM)虛擬機使用的磁盤文件格式,本文將從其實現原理,支持特性,以及讀寫效率等進行對比和分析,最後還要介紹這兩種格式的磁盤文件如何轉化。

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

[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 =offwritethroughwriteback 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 =offwriteback 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 格式不具有的功能。

Ubuntu 12.04之找不到Qemu命令 http://www.linuxidc.com/Linux/2012-11/73419.htm

Arch Linux上安裝QEMU+EFI BIOS http://www.linuxidc.com/Linux/2013-02/79560.htm

QEMU的翻譯框架及調試工具 http://www.linuxidc.com/Linux/2012-09/71211.htm

QEMU 的詳細介紹:請點這裡
QEMU 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved