欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Qcow2鏡像格式解析
本文是一篇翻譯文章,邊看邊學(xué)習邊翻譯,目前有些地方翻譯的不是太好。之后會(huì )逐步做修正,并結合代碼以及圖表來(lái)深入剖析。
原文鏈接:https://people.gnome.org/~markmc/qcow-image-format.html

Qcow2鏡像格式是qemu支持的磁盤(pán)鏡像格式之一。qcow2的表現形式為在一個(gè)文件中模擬一個(gè)固定大小的塊設備。對與qcow2格式,相對于raw格式來(lái)說(shuō),有幾個(gè)優(yōu)點(diǎn):
  1. 更小的文件大小,即使是不支持holes的文件系統也可以(這樣的話(huà),ls跟du看到的就一樣了);
  2. Copy-on-write的支持;
  3. 快照的支持,可以維護多個(gè)快照;
  4. 基于zlib的壓縮;
  5. AES加密
qemu-img命令可以用來(lái)創(chuàng )建qcow2鏡像,或者將qcow2文件轉換成raw格式文件,等其它功能:
  $> qemu-img create -f qcow2 test.qcow2 4G
  Formating 'test.qcow2', fmt=qcow2, size=4194304 kB
  $> qemu-img convert test.qcow2 -O raw test.img


qcow2 Header
每一個(gè)qcow2文件都是以一個(gè)固定格式的數據頭開(kāi)始的,其以大端模式存放,格式如下:
  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;

  • 頭4個(gè)字節包含了字符'Q', 'F', 'I',并以0xfb結尾;
  • 之后的4個(gè)字節包含了這個(gè)文件所用的格式版本,當前存在兩種版本的格式,版本1和版本2。在本文,我們討論的是版本2,即qcow2。版本1將在本文最后做簡(jiǎn)要介紹;
  • backing_file_offset字段給出相對于qcow2文件起始位置的偏移,指出一個(gè)字符串的位置,該字符串為backing file文件的絕對路徑。由于該字符串不是以'\0'結束,所以backing_file_size指出字符串的長(cháng)度。如果當前鏡像是一個(gè)copy-on-write鏡像,則存在backing file文件,否則沒(méi)有;
  • cluster_bits字段,決定了怎樣映射鏡像偏移地址到文件偏移地址,其決定了在一個(gè)簇中,將拿偏移地址的多少位(低位)來(lái)作為索引。L2表占據一個(gè)單獨的簇,包含若干8字節的項,cluster_bits最少用3bits作為L(cháng)2表的索引。L2表的詳細介紹,見(jiàn)下一節的2級索引;
  • size字段指示鏡像以塊設備呈現時(shí)的大小,單位字節;
  • crypt_method只有兩種值,0表示沒(méi)有加密,1表示采用了AES加密;
  • l1_size字段指示了在L1表中,可用的8字節項的個(gè)數,l1_table_offset字段給出了L1 table的文件偏移;
  • 相似的,refcount_table_offset字段給出了refcount table的文件偏移,refcount_table_clusters字段描述了refcount table大小(單位為clusters);
  • nb_snapshots字段給出了當前鏡像中有多少個(gè)快照,snapshots_offset字段給出了QCowSnapshotHeader headers的文件偏移,每個(gè)快照都會(huì )有這樣一個(gè)header。

一個(gè)典型的鏡像文件,其布局如下:
  • 一個(gè)header, 如上描述;
  • 在下一個(gè)簇開(kāi)始,存放L1 table;
  • refcount table,仍然是簇對齊的;
  • 一個(gè)或者多個(gè)的refcount blocks;
  • Snapshot headers,第一個(gè)header要求簇對齊,之后的header要求8字節對齊;
  • L2 tables,每一個(gè)table占據一個(gè)單獨的cluster;
  • Data clusters。


2級索引
對于qcow2格式,塊設備的內容被保存在cluster中。每個(gè)cluster包含了若干個(gè)sector,每個(gè)sector有512個(gè)字節。

為了通過(guò)給定的鏡像地址找到指定的cluster,必須經(jīng)過(guò)1級表和2級表的轉換。例如,假設cluster_bits為12,則地址會(huì )被切分成如下三份:
  • 低12位用來(lái)定位一個(gè)4Kb的簇內偏移;
  • 之后的9位為一個(gè)512項的數組的偏移,每一項為一個(gè)8字節的文件偏移,即L2 table。 這里的9位是這么算出來(lái)的, l2_bits = cluster_bits - 3,L2 table是一個(gè)單獨的包含若干8字節項的cluster;
  • 剩下的43位為另外一個(gè)8字節的文件偏移的數組的偏移,即L1 table。
注意,L1 table的最小值,可以通過(guò)給定磁盤(pán)鏡像的大小來(lái)計算,公式如下:
l1_size = round_up(disk_size / (cluster_size * l2_size), cluster_size)

總的來(lái)說(shuō),為了將磁盤(pán)鏡像地址映射到鏡像文件偏移,需要經(jīng)歷以下幾步:
  1. 通過(guò)qcow2 header中的l1_table_offset字段獲取L1 table的地址;
  2. 使用高(64 - l2_bits - cluser_bits)位的地址來(lái)索引L1 table,L1 table是一個(gè)數組,數組元素是一個(gè)64位的數;
  3. 通過(guò)L1 table中的表項來(lái)獲取L2 table的地址;
  4. 通過(guò)L2 table中的表項來(lái)獲取cluster的地址;
  5. 剩余的cluster_bits位來(lái)索引cluster內的位置。
如果找到的L1 table或L2 table的地址偏移為0,則表示磁盤(pán)鏡像對應的區域尚未分配。

還需要注意的是,L1或L2 table的地址的高2位被保留下來(lái),拿來(lái)置"copied"和"compressed"標記。具體細節見(jiàn)下節"引用計數"。


引用計數
每一個(gè)cluster都有一個(gè)引用計數,cluster可以被刪除,但前提條件是沒(méi)有任何快照再使用這個(gè)cluster。

針對每一個(gè)cluster的2個(gè)字節的引用計數,存放在cluster sized blocks。通過(guò)refcount_table_offset字段可以獲取到refcount table的位置,refcount_table_clusters字段給出refcount table的大?。▎挝粸閏luster),refcount table給出了這些refcount blocks在鏡像文件中的偏移地址。

為了獲取一個(gè)給定的cluster的引用計數,你需要將cluster offset劃分成refcount table offset和refcount block offset。一個(gè)refcount block是一個(gè)單獨的cluster,這個(gè)cluster里包含了若干個(gè)2字節的項,低(cluster_size -1)位作為block offset,剩余的位作為table offset。

qcow2有一個(gè)優(yōu)化處理,任何一個(gè)L1或L2表項指向的cluster的引用計數為1,則L1/L2表項的最高有效位被置上“copied”標記。這表明沒(méi)有快照在使用這個(gè)cluster,所以這個(gè)cluster可以馬上寫(xiě)入數據,而不需要復制一份給快照使用。


Copy-on-Write特性
一個(gè)qcow2鏡像可以用來(lái)保存其它鏡像的變化部分,從而不實(shí)際影響到原有磁盤(pán)的內容。這就是增量鏡像,看著(zhù)就像一個(gè)獨立的鏡像,其所有數據都是從模板鏡像獲取的。僅當clusters中的內容跟模板鏡像不一樣的時(shí)候,這些cluster才會(huì )被保存到增量鏡像中。

寫(xiě)時(shí)復制的實(shí)現方式比較簡(jiǎn)單。增量鏡像會(huì )在qcow2 header中的backing_file_offset字段指示一個(gè)字符串在qcow2文件內的偏移,該字符串是模板鏡像文件的絕對路徑,backing_file_size字段指明字符串的長(cháng)度。

當要從增量鏡像中讀取一個(gè)cluster時(shí),qemu會(huì )先檢查這個(gè)cluster在增量鏡像中有沒(méi)有被分配。如果沒(méi)有,則會(huì )去讀模板鏡像中的對應位置。

快照
快照跟寫(xiě)時(shí)復制的概念比較類(lèi)似。

進(jìn)一步解釋——一個(gè)增量鏡像也可以被說(shuō)成是一個(gè)“快照”,因為它確實(shí)可以作為模板鏡像的一個(gè)快照。我們可以創(chuàng )建多個(gè)增量鏡像來(lái)實(shí)現創(chuàng )建多個(gè)“快照”,每一個(gè)增量鏡像都引用同一個(gè)模板鏡像。模板鏡像必須保持為只讀,增量鏡像則為可寫(xiě)的。

快照——"實(shí)際的快照"——存在于一個(gè)鏡像里面,這個(gè)鏡像既當模板,也當增量鏡像。每一個(gè)快照都是鏡像在過(guò)去某個(gè)瞬間的只讀記錄。鏡像仍然可寫(xiě),寫(xiě)時(shí)復制出來(lái)的cluster會(huì )被不同的快照引用。

每個(gè)快照都對應一個(gè)描述信息結構體:
  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;

各字段介紹如下:
  • 快照有名字和ID,都是字符串,id_str_size,name_size給出字符串長(cháng)度,字符串緊接在QCowSnapshotHeader后面;
  • 快照至少有原來(lái)的L1 table的副本,其通過(guò)l1_table_offset和l1_size來(lái)定位;
  • 在快照被創(chuàng )建的時(shí)候,qemu會(huì )調用gettimeofday(),快照時(shí)間被保存在date_sec和date_nsec字段中;
  • vm_clock_nsec給出VM clock當前的狀態(tài);
  • vm_state_size表示作為快照的一部分被保存的虛擬機狀態(tài)的大小。這個(gè)狀態(tài)被保存在原來(lái)L1 table的位置,直接在鏡像header的后面;
  • extra_data_size表示在QCowSnapshotHeader之后的擴展數據的長(cháng)度,不包括id和name字符串。這一段擴展數據是留給以后用的。
創(chuàng )建一個(gè)快照,就會(huì )添加一個(gè)QCowSnapshotHeader,然后復制一份L1 table,同時(shí)會(huì )增加所有L2 table和數據clusters的被L1 table引用的引用計數。打完快照之后,如果任何在這個(gè)鏡像中的L2 table或者data clusters被修改了——也就是,如果一個(gè)cluster的引用計數大于1,且"copied"標記被置上了——qemu則會(huì )先復制一份這個(gè)cluster,然后再寫(xiě)入數據。就這樣,所有的快照都不會(huì )被修改。


壓縮
qcow2鏡像格式支持壓縮特性,其允許每一個(gè)cluster獨立的通過(guò)zlib進(jìn)行壓縮。

/*cluster offset表示一個(gè)簇在qcow2文件中的偏移,其最高的2位是標記位*/
從L2 table中獲取cluster offset的流程如下:
  • 如果cluster offset的第二最高有效位是1,則這是一個(gè)被壓縮的cluster;
  • cluster offset中之后的cluster_bits - 8 位是這個(gè)壓縮過(guò)的cluster的大小,單位是sectors;
  • cluster offset剩余的位是壓縮的cluster在文件中的實(shí)際偏移地址。

加密
qcow2格式,也支持針對cluster的加密。
如果QCowHeader中的crypt_method字段被置為1,則會(huì )采用一個(gè)16個(gè)字符的密碼作為128位AES key。
每一個(gè)Cluster中的每一個(gè)sector都是通過(guò)AES密碼塊鏈接模式來(lái)單獨加密,采用sector的偏移地址(小端模式)來(lái)作為128位初始化向量的頭64位。

qcow鏡像——上一代鏡像
qcow2格式相對于qcow格式的不同點(diǎn)有:
  1. 支持快照的概念,qcow只支持增量鏡像;
  2. 在qcow2中,引入了cluster的引用計數的概念;引用計數也被用來(lái)支持快照;
  3. 在qcow2中,L2 table將一直占一個(gè)單獨的cluster; 之前,是通過(guò)QCowHeader中的l2_bits來(lái)確定的;
  4. 壓縮的cluster的大小,現在單位為sector,之前是字節。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
虛擬化存儲的學(xué)習筆記
KVM虛擬機快照備份
kvm虛擬化學(xué)習筆記(十)之kvm虛擬機快照備份
Qemu快照(snapshot)機制原理及關(guān)鍵技術(shù)理解
使用qmeu
ClickHouse常用命令,基本數據類(lèi)型
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久