本文首發於個人公衆號 Linux雲計算網絡(id: cloud_dev),專一於乾貨分享,號內有 10T 書籍和視頻資源,後臺回覆「1024」便可領取,歡迎你們關注,二維碼文末能夠掃。前端
virtio 是一種 I/O 半虛擬化解決方案,是一套通用 I/O 設備虛擬化的程序,是對半虛擬化 Hypervisor 中的一組通用 I/O 設備的抽象。提供了一套上層應用與各 Hypervisor 虛擬化設備(KVM,Xen,VMware等)之間的通訊框架和編程接口,減小跨平臺所帶來的兼容性問題,大大提升驅動程序開發效率。編程
在徹底虛擬化的解決方案中,guest VM 要使用底層 host 資源,須要 Hypervisor 來截獲全部的請求指令,而後模擬出這些指令的行爲,這樣勢必會帶來不少性能上的開銷。半虛擬化經過底層硬件輔助的方式,將部分不必虛擬化的指令經過硬件來完成,Hypervisor 只負責完成部分指令的虛擬化,要作到這點,須要 guest 來配合,guest 完成不一樣設備的前端驅動程序,Hypervisor 配合 guest 完成相應的後端驅動程序,這樣二者之間經過某種交互機制就能夠實現高效的虛擬化過程。後端
因爲不一樣 guest 前端設備其工做邏輯大同小異(如塊設備、網絡設備、PCI設備、balloon驅動等),單獨爲每一個設備定義一套接口實屬沒有必要,並且還要考慮擴平臺的兼容性問題,另外,不一樣後端 Hypervisor 的實現方式也大同小異(如KVM、Xen等),這個時候,就須要一套通用框架和標準接口(協議)來完成二者之間的交互過程,virtio 就是這樣一套標準,它極大地解決了這些不通用的問題。數組
從整體上看,virtio 能夠分爲四層,包括前端 guest 中各類驅動程序模塊,後端 Hypervisor (實如今Qemu上)上的處理程序模塊,中間用於先後端通訊的 virtio 層和 virtio-ring 層,virtio 這一層實現的是虛擬隊列接口,算是先後端通訊的橋樑,而 virtio-ring 則是該橋樑的具體實現,它實現了兩個環形緩衝區,分別用於保存前端驅動程序和後端處理程序執行的信息。網絡
嚴格來講,virtio 和 virtio-ring 能夠看作是一層,virtio-ring 實現了 virtio 的具體通訊機制和數據流程。或者這麼理解可能更好,virtio 層屬於控制層,負責先後端之間的通知機制(kick,notify)和控制流程,而 virtio-vring 則負責具體數據流轉發。架構
vring 主要經過兩個環形緩衝區來完成數據流的轉發,以下圖所示。框架
vring 包含三個部分,描述符數組 desc,可用的 available ring 和使用過的 used ring。函數
desc 用於存儲一些關聯的描述符,每一個描述符記錄一個對 buffer 的描述,available ring 則用於 guest 端表示當前有哪些描述符是可用的,而 used ring 則表示 host 端哪些描述符已經被使用。工具
Virtio 使用 virtqueue 來實現 I/O 機制,每一個 virtqueue 就是一個承載大量數據的隊列,具體使用多少個隊列取決於需求,例如,virtio 網絡驅動程序(virtio-net)使用兩個隊列(一個用於接受,另外一個用於發送),而 virtio 塊驅動程序(virtio-blk)僅使用一個隊列。性能
具體的,假設 guest 要向 host 發送數據,首先,guest 經過函數 virtqueue_add_buf 將存有數據的 buffer 添加到 virtqueue 中,而後調用 virtqueue_kick 函數,virtqueue_kick 調用 virtqueue_notify 函數,經過寫入寄存器的方式來通知到 host。host 調用 virtqueue_get_buf 來獲取 virtqueue 中收到的數據。
存放數據的 buffer 是一種分散-彙集的數組,由 desc 結構來承載,以下是一種經常使用的 desc 的結構:
當 guest 向 virtqueue 中寫數據時,其實是向 desc 結構指向的 buffer 中填充數據,完了會更新 available ring,而後再通知 host。
當 host 收到接收數據的通知時,首先從 desc 指向的 buffer 中找到 available ring 中添加的 buffer,映射內存,同時更新 used ring,並通知 guest 接收數據完畢。
virtio 是 guest 與 host 之間通訊的潤滑劑,提供了一套通用框架和標準接口或協議來完成二者之間的交互過程,極大地解決了各類驅動程序和不一樣虛擬化解決方案之間的適配問題。
virtio 抽象了一套 vring 接口來完成 guest 和 host 之間的數據收發過程,結構新穎,接口清晰。
個人公衆號 「Linux雲計算網絡」(id: cloud_dev) ,號內有 10T 書籍和視頻資源,後臺回覆 「1024」 便可領取,分享的內容包括但不限於 Linux、網絡、雲計算虛擬化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++編程技術等內容,歡迎你們關注。