mysql qcow2_qcow2文件格式分析

mysql qcow2_qcow2文件格式分析qcow 文件格式描述官网说明文档 vim 某虚拟机的 qcow2 文件 xxd0 3 magicQCOWmag QFI xfb 4 个字节固定的标识符 4 7 versionVersi validvaluesa 版本号 2 或者 38 15 backing file offset 文件路径字符串相对于

qcow文件格式描述

官网说明文档:

vim [某虚拟机的qcow2文件]

%!xxd

0 – 3 : magic QCOW magic string (“QFI\xfb”) 4个字节固定的标识符

4 – 7 : version Version number (valid values are 2 and 3) 版本号,2或者3

8 – 15 : backing_file_offset 文件路径字符串相对于文件起始位置的偏移地址,这个字符串不是以0结束的。该值为0时,表示该镜像没有 backing file

0000 0000 0000 0118 -> 0000 0001 0001 1000 256+24=280 看左边的地址定位

16 – 19 : backing_file_size 文件路径字符串长度,单位是字节数。必须小于1023字节。镜像没有backing file时,该值无意义

0000 0079 0111 1001 = 121

400 280

0x00000190-0x00000118 =ox78 + 1 = 121

20 – 23 : cluster_bits cluster 位数,代表了 cluster 大小(1 << cluster_bits 就是 cluster 的大小)。不能小于9,也就是每个 cluster 大小不能小于 512个字节。 Note:新版本的qemu启用了最大 2MB 的 cluster 大小。

0000 0010 -> 00010000 16 bit :2^16:64k cluster大小

24 – 31 : size 虚拟磁盘的大小,单位字节,这个是呈现给用户的大小(virt-df查看),不是文件实际大小

0000 0002 8000 0000 2 * 2^32 + 8 * 2^28=2^33 + 2^31 = 10G

32 – 35 : crypt_method 0 – 未加密;1 – AES加密

0000 0000

36 – 39 : l1_size L1 table项数

0000 0014= 20

40 – 47 : l1_table_offset L1 table 相对于镜像文件起始位置的偏移, 必须与 cluster 对齐

0000 0000 0004 0000= 4 * 2^12 看左边的地址即可

48 – 55 : refcount_table_offset refcount table 相对于镜像文件起始位置的偏移。必须与 cluster 对齐

0000 0000 0001 0000

56 – 59 : refcount_table_clusters refcount table 占用了多少个 cluster

0000 0001

60 – 63 : nb_snapshots 镜像文件中包含了多少个快照。

0000 0000

64 – 71 : snapshots_offset 快照table相对于镜像文件起始位置的偏移,必须与cluster对齐

0000 0000 0000 0000

版本号如果为3,头部还会有以下附加的信息,在版本2中,这些值都是0,除非特别说明:

72 – 79 : incompatible_features 未实现的特征的位掩码,在解析文件的时候,如果发现某个未知的位被设置为1,就是需要报错的时候了。

0000 0000 0000 0000

Bit 0 脏位。如果该位为1,refcounts可能和实际情况是不一致的,在解析的时候需要扫描一遍 L1/L2 table 来修复 refcounts。

Bit 1 损坏位。如果该位为1,任何数据结构可能损坏,且镜像不应该被写。

Bits 2-63 Reserved (set to 0) 保留,应该为0。

Bitmask of incompatible features. An implementation must

fail to open an image if an unknown bit is set.

Bit 0: Dirty bit. If this bit is set then refcounts

may be inconsistent, make sure to scan L1/L2

tables to repair refcounts before accessing the

image.

Bit 1: Corrupt bit. If this bit is set then any data

structure may be corrupt and the image must not

be written to (unless for regaining

consistency).

Bits 2-63: Reserved (set to 0)

80 – 87 : compatible_features 兼容特征的位掩码。解析的时候完全可以忽略这些位。

0000 0000 0000 0000

Bit 0: 该位为1,则 lazy refcount 更新可以被使用。 意味着 dirty bit 为1,并且推迟refcount 元数据的更新。

Bits 1-63: Reserved (set to 0)

88 – 95 : autoclear_features 我的理解是…… 对于这些autoclear feature,在处理镜像时,如果某一位含义未知,则应该先将其设置为0,再进行写镜像操作。

Bitmask of auto-clear features. An implementation may only write to an image with unknown auto-clear features if it clears the respective bits from this field first.

0000 0000 0000 0000

Bit 0:这一位表示 bitmap extension 数据一致性。 如果这一位为1,但不存在 bitmaps extension,则应该报错;如果存在 bitmap extension 但这一位为0,则应认为 bitmap extension data 不一致(存在问题?)。

Bits 1-63: Reserved (set to 0)

96 – 99 : refcount_order refcount block项的宽度(bit宽度),版本2时,固定为4,也就是说 refcount_bits = 16.该值不超过6,也就是 refcount_bits 不超过 64。refcount_bits = 1 << refcount_order

0000 0004

100 – 103: header_length 文件头结构体的长度,版本2时,长度固定为72字节。

0000 0068104字节 也就是刚好到该位置

关于header extensions,头部扩展性选项

紧接着镜像的文件头,存储的是可选的多个 header extensions,header extensions定义

typedef struct Qcow2UnknownHeaderExtension {

uint32_t magic;

uint32_t len;

QLIST_ENTRY(Qcow2UnknownHeaderExtension) next;

uint8_t data[];

} Qcow2UnknownHeaderExtension;

字段说明

Byte 0 – 3: Header extension 的类型:

0x00000000 – End of the header extension area 我理解该值应该是表示没有header extension选项

0xE2792ACA – Backing file format namee279 2aca示例中刚好是这个值

0x6803f857 – Feature name table

0x – Bitmaps extension

other – Unknown header extension, can be safely

ignored

4 – 7: header extension 的数据长度0000 00055byte

8 – n: Header extension数据部分7163 6f77 32

n – m: 为对齐到8字节的填充部分00 0000

后面接着

6803 f857 00000090和后面紧接着的Feature name table有关 长度为00000090144byte

除非特别说明,每个extension类型在一个镜像里应该只会出现一次。如果有Backing file ,则在the backing file name should be stored in the remaining space between the end of the header extension area and the end of the first cluster. It is not allowed to store other data here, so that an implementation can safely modify the header and add extensions without harming data of compatible features that it doesn’t support. Compatible features that need space for additional data can use a header extension.

关于 Feature name table 和 Bitmaps extension 两种 extension 类型结构的说明

Feature name table

eature name table 是可选项:记录镜像的某种特性。应用程序使用该字段记录某种未知的特性错误信息(稍后才知道的特性),eature name table的条目数取决于header extension data的长度,每一项的结构如下:

00000080: 00006469 7274 7920 6269 7400 0000 0000 ..dirty bit…..

00000090: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000b0: 0001 636f 7272 7570 7420 6269 7400 0000 ..corrupt bit…

000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000e0: 0100 6c61 7a79 2072 6566 636f 756e 7473 ..lazy refcounts

000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000100: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

三种future name table刚好144byte

Byte 0: 特性的类型 (select feature bitmap)

0: Incompatible feature参看前面 应该是dirty bit 和 corrupt bit

1: Compatible feature

2: Autoclear feature

1: Bit number within the selected feature bitmap (valid

values: 0-63)

2 – 47: Feature name (padded with zeros, but not necessarily null

terminated if it has full length)

Bitmaps extension

bitmaps extension为可选项.可用于存储虚拟disk相关的bitmap . 当前只有一种 dirty tracking bitmap,跟踪 虚disk从某个时间点的变化。在auto-clear feature设置的情况下,需要考虑extension的数据。

Byte 0 – 3: nb_bitmaps image中bitmap的数量,大于等于1

The number of bitmaps contained in the image. Must be

greater than or equal to 1.

注意: 当前Qemu 一个image支持65535个bitmaps

4 – 7: 保留为0.

8 – 15: bitmap_directory_size

Size of the bitmap directory in bytes. It is the cumulative

size of all (nb_bitmaps) bitmap headers.

16 – 23: bitmap_directory_offset

Offset into the image file at which the bitmap directory

starts. Must be aligned to a cluster boundary.

Host cluster management

有 host cluster 和 guest cluster 的区别.这里解释了前面一直提到的refcount。对于每一个host cluster,qcow2维护了一个refcount表,应该是引用计数的概念,当refcount为0时,表示该cluster是未分配的,1表示是在使用的,>=2时表示在被使用,并且所有的写操作都要进行COW(copy on write)操作。

采用了两层表来维护管理 refcounts,第一层叫 refcount table,是可变大小的(refcount table 的 size 存储在header里),refcount table 的每一项覆盖多个 cluster,当然,在镜像文件中refcount table是连续存储的。refcount table 包含了多个指针,指向了第二层结构体,第二层结构被称为 refcount block,一个refcount block在大小上就是一个cluster。(意思就是,block也是存在一个个cluster里的),以下是根据镜像偏移量 offset,获得某个cluster对应引用计数的方法.

refcount_block_entries = (cluster_size * 8 / refcount_bits)

refcount_block_index = (offset / cluster_size) % refcount_block_entries

refcount_table_index = (offset / cluster_size) / refcount_block_entries

refcount_block = load_cluster(refcount_table[refcount_table_index]);

return refcount_block[refcount_block_index];

注:各种变量前文有述,这里回顾一下

cluster_size = 1 << cluster_bits //最小 512 bytes

refcount_bits = 16 //in version 2

以版本2为例:

cluster_size是一个cluster的字节数,对于一个qcow2文件来说,每个cluster都是固定大小的,比如512字节。

refcount_bits固定是16,也就是2bytes,因为refcount block也要按照cluster的大小来存储,所以每个cluster能够存储的block个数: refcount_block_entries = cluster_size / 2 = 256 。

refcount_table 的一个单元对应 256 个 refcount_block,存在一个cluster里。

每个block里有2个字节(16位),记录了某个cluster的引用计数。

所以计算某个 offset 所在的 cluster 引用计数的办法,先 offset / cluster_size 得到这个offset对应的是第几个cluster,然后在refcount table里找,存在table的第几个单元里,最后在这个单元里找是第几个block存着引用计数。

下面是 refcount table 和 refcount block 的结构体定义,理解了上面这段的话,这里挺简单的了。

Refcount table entry:

Bit 0 – 8: Reserved (set to 0)

9 – 63: Bits 9-63 of the offset into the image file at which the

refcount block starts. Must be aligned to a cluster

boundary.

If this is 0, the corresponding refcount block has not yet

been allocated. All refcounts managed by this refcount block

are 0.

Refcount block entry (x = refcount_bits – 1): 这里为16-1=15

Bit 0 – x: Reference count of the cluster. If refcount_bits implies a

sub-byte width, note that bit 0 means the least significant

bit in this context.

00000000: 5146 49fb 0000 0003 0000 0000 0000 0118 QFI………….

00000010:0000 00 0010 0000 0002 8000 0000 …y…………

00000020: 0000 0000 0000 0014 0000 0000 0004 0000 …………….

00000030: 0000 0000 0001 0000 0000 0001 0000 0000 …………….

00000040: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000050: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000060: 0000 0004 0000 0068 e279 2aca 0000 0005 …….h.y*…..

00000070: 7163 6f77 3200 0000 6803 f857 00000090 qcow2…h..W….

00000080: 00006469 7274 7920 6269 7400 0000 0000 ..dirty bit…..

00000090: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000b0: 0001 636f 7272 7570 7420 6269 7400 0000 ..corrupt bit…

000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000000e0: 0100 6c61 7a79 2072 6566 636f 756e 7473 ..lazy refcounts

000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000100: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000110: 0000 0000 0000 0000 2f64 6174 6130 2f7a ……../data0/z

00000120: 7374 6163 6b2d 7072 696d 6172 792d 7374 stack-primary-st

00000130: 6f72 6167 652f 696d 6167 6563 6163 6865 orage/imagecache

00000140: 2f74 656d 706c 6174 652f 3365 3839 6131 /template/3e89a1

00000150: 3965 6566 3231 3433 3738 6166 3437 3262 9eefaf472b

00000160: 3136 3162 3165 6662 3562 2f33 6538 3961 161b1efb5b/3e89a

00000170: 3139 6565 6632 3134 3337 3861 6634 3732 19eefaf472

00000180: 6231 3631 6231 6566 6235 622e 7163 6f77 b161b1efb5b.qcow

00000190: 3200 0000 0000 0000 0000 0000 0000 0000 2……………

000001a0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000001b0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000001c0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

000001f0: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000200: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000210: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000220: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000230: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

00000240: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212530.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午7:50
下一篇 2026年3月18日 下午7:51


相关推荐

  • 从零实现云服务器,小龙虾链接钉钉(Openclaw)

    从零实现云服务器,小龙虾链接钉钉(Openclaw)

    2026年3月13日
    2
  • Centos 查看文件夹大小

    Centos 查看文件夹大小查看文件夹大小查询当前目录总大小可以使用 du sh 其中 s 代表统计汇总的意思 即只输出一个总和大小 含义命令查看指定目录的总大小 du sh 目录名称查看当前目录的总大小 du sh 查看当前目录 1 层深各文件夹大小 du hmax depth 1 查看当前目录 2 层深各文件夹大小 du hmax depth 2 查看文件大小含义命令以字节显示文件大小 ls ll 以 KB MB 显示文件大小 ls lh 当前目录

    2026年3月17日
    2
  • 前端模块化理解

    前端模块化理解转至 http www cnblogs com lvdabao p js modules develop html 在 JavaScript 发展初期就是为了实现简单的页面交互逻辑 寥寥数语即可 如今 CPU 浏览器性能得到了极大的提升 很多页面逻辑迁移到了客户端 表单验证等 随着 web2 0 时代的到来 Ajax 技术得到广泛应用 jQuery 等前端库层出不穷 前端代码日益膨胀 这时候 JavaScr

    2026年3月16日
    3
  • onpropertychange事件(on intention)

    onpropertychange事件(on intention)IE下,当一个HTML元素的属性改变的时候,都能通过onpropertychange来捕获。例如一个对象的value属性被页面的脚本修改的时候,onchange无法捕获到,而onpropertychange却能够捕获。(是实时性捕捉到的)也就是说:onpropertychange能及时捕获属性值的变化,而onchange在属性值改变时还必须使得当前元素失去焦点(onblur)才可以激活该事件!

    2022年4月18日
    123
  • 腾讯承认对AI“动作慢了”,然后呢?

    腾讯承认对AI“动作慢了”,然后呢?

    2026年3月13日
    1
  • 初探js逆向「建议收藏」

    初探js逆向「建议收藏」转载自三尾先生博客初探js逆向在开始之前想先说下阅读完三尾先生这篇文章的一点个人理解,文章写得挺好的,很值得新手学习了解,首先谈下逆向激活成功教程思路1.需要逆向的时候一般是遇到了加密问题,加密情况有参数加密,有结果加密。但不管怎样的加密只要页面能正常显示,那就有解密过程!2.先找到加密的字段名,通过字段名在sources全局搜索3.在含有这些字段的位置打断点,一般sources里看到的会是一行的压缩代码,我们可以通过点击左下角的双大括号格式化js代码然后通过断点一步步查看参数在哪一步骤发生了变

    2022年6月22日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号