?virtio 簡(jiǎn)介
virtio 是一種 I/O 半虛擬化解決方案,是一套通用 I/O 設(shè)備虛擬化的程序,是對(duì)半虛擬化 Hypervisor 中的一組通用 I/O 設(shè)備的抽象。提供了一套上層應(yīng)用與各 Hypervisor 虛擬化設(shè)備(KVM,Xen,VMware等)之間的通信框架和編程接口,減少跨平臺(tái)所帶來(lái)的兼容性問(wèn)題,大大提高驅(qū)動(dòng)程序開(kāi)發(fā)效率。
為什么是 virtio#在完全虛擬化的解決方案中,guest VM 要使用底層 host 資源,需要 Hypervisor 來(lái)截獲所有的請(qǐng)求指令,然后模擬出這些指令的行為,這樣勢(shì)必會(huì)帶來(lái)很多性能上的開(kāi)銷。半虛擬化通過(guò)底層硬件輔助的方式,將部分沒(méi)必要虛擬化的指令通過(guò)硬件來(lái)完成,Hypervisor 只負(fù)責(zé)完成部分指令的虛擬化,要做到這點(diǎn),需要 guest 來(lái)配合,guest 完成不同設(shè)備的前端驅(qū)動(dòng)程序,Hypervisor 配合 guest 完成相應(yīng)的后端驅(qū)動(dòng)程序,這樣兩者之間通過(guò)某種交互機(jī)制就可以實(shí)現(xiàn)高效的虛擬化過(guò)程。
由于不同 guest 前端設(shè)備其工作邏輯大同小異(如塊設(shè)備、網(wǎng)絡(luò)設(shè)備、PCI設(shè)備、balloon驅(qū)動(dòng)等),單獨(dú)為每個(gè)設(shè)備定義一套接口實(shí)屬?zèng)]有必要,而且還要考慮擴(kuò)平臺(tái)的兼容性問(wèn)題,另外,不同后端 Hypervisor 的實(shí)現(xiàn)方式也大同小異(如KVM、Xen等),這個(gè)時(shí)候,就需要一套通用框架和標(biāo)準(zhǔn)接口(協(xié)議)來(lái)完成兩者之間的交互過(guò)程,virtio 就是這樣一套標(biāo)準(zhǔn),它極大地解決了這些不通用的問(wèn)題。
virtio 的架構(gòu)#從總體上看,virtio 可以分為四層,包括前端 guest 中各種驅(qū)動(dòng)程序模塊,后端 Hypervisor (實(shí)現(xiàn)在Qemu上)上的處理程序模塊,中間用于前后端通信的 virtio 層和 virtio-ring 層,virtio 這一層實(shí)現(xiàn)的是虛擬隊(duì)列接口,算是前后端通信的橋梁,而 virtio-ring 則是該橋梁的具體實(shí)現(xiàn),它實(shí)現(xiàn)了兩個(gè)環(huán)形緩沖區(qū),分別用于保存前端驅(qū)動(dòng)程序和后端處理程序執(zhí)行的信息。
嚴(yán)格來(lái)說(shuō),virtio 和 virtio-ring 可以看做是一層,virtio-ring 實(shí)現(xiàn)了 virtio 的具體通信機(jī)制和數(shù)據(jù)流程?;蛘哌@么理解可能更好,virtio 層屬于控制層,負(fù)責(zé)前后端之間的通知機(jī)制(kick,notify)和控制流程,而 virtio-vring 則負(fù)責(zé)具體數(shù)據(jù)流轉(zhuǎn)發(fā)。
virtio 數(shù)據(jù)流交互機(jī)制#vring 主要通過(guò)兩個(gè)環(huán)形緩沖區(qū)來(lái)完成數(shù)據(jù)流的轉(zhuǎn)發(fā),如下圖所示。
vring 包含三個(gè)部分,描述符數(shù)組 desc,可用的 available ring 和使用過(guò)的 used ring。
desc 用于存儲(chǔ)一些關(guān)聯(lián)的描述符,每個(gè)描述符記錄一個(gè)對(duì) buffer 的描述,available ring 則用于 guest 端表示當(dāng)前有哪些描述符是可用的,而 used ring 則表示 host 端哪些描述符已經(jīng)被使用。
Virtio 使用 virtqueue 來(lái)實(shí)現(xiàn) I/O 機(jī)制,每個(gè) virtqueue 就是一個(gè)承載大量數(shù)據(jù)的隊(duì)列,具體使用多少個(gè)隊(duì)列取決于需求,例如,virtio 網(wǎng)絡(luò)驅(qū)動(dòng)程序(virtio-net)使用兩個(gè)隊(duì)列(一個(gè)用于接受,另一個(gè)用于發(fā)送),而 virtio 塊驅(qū)動(dòng)程序(virtio-blk)僅使用一個(gè)隊(duì)列。
具體的,假設(shè) guest 要向 host 發(fā)送數(shù)據(jù),首先,guest 通過(guò)函數(shù) virtqueue_add_buf 將存有數(shù)據(jù)的 buffer 添加到 virtqueue 中,然后調(diào)用 virtqueue_kick 函數(shù),virtqueue_kick 調(diào)用 virtqueue_notify 函數(shù),通過(guò)寫(xiě)入寄存器的方式來(lái)通知到 host。host 調(diào)用 virtqueue_get_buf 來(lái)獲取 virtqueue 中收到的數(shù)據(jù)。
存放數(shù)據(jù)的 buffer 是一種分散-聚集的數(shù)組,由 desc 結(jié)構(gòu)來(lái)承載,如下是一種常用的 desc 的結(jié)構(gòu):
當(dāng) guest 向 virtqueue 中寫(xiě)數(shù)據(jù)時(shí),實(shí)際上是向 desc 結(jié)構(gòu)指向的 buffer 中填充數(shù)據(jù),完了會(huì)更新 available ring,然后再通知 host。
當(dāng) host 收到接收數(shù)據(jù)的通知時(shí),首先從 desc 指向的 buffer 中找到 available ring 中添加的 buffer,映射內(nèi)存,同時(shí)更新 used ring,并通知 guest 接收數(shù)據(jù)完畢。
總結(jié):#virtio 是 guest 與 host 之間通信的潤(rùn)滑劑,提供了一套通用框架和標(biāo)準(zhǔn)接口或協(xié)議來(lái)完成兩者之間的交互過(guò)程,極大地解決了各種驅(qū)動(dòng)程序和不同虛擬化解決方案之間的適配問(wèn)題。
virtio 抽象了一套 vring 接口來(lái)完成 guest 和 host 之間的數(shù)據(jù)收發(fā)過(guò)程,結(jié)構(gòu)新穎,接口清晰。
virtio 簡(jiǎn)介 - bakari - 博客園 (cnblogs.com)
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。