91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

KVM 虛擬化原理中的網絡IO虛擬化是怎樣的

發布時間:2021-12-03 17:20:40 來源:億速云 閱讀:152 作者:柒染 欄目:云計算

KVM 虛擬化原理中的網絡IO虛擬化是怎樣的,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

IO 虛擬化簡介

前面的文章介紹了KVM的啟動過程,CPU虛擬化,內存虛擬化原理。作為一個完整的風諾依曼計算機系統,必然有輸入計算輸出這個步驟。傳統的IO包括了網絡設備IO,塊設備IO,字符設備IO等等,在KVM虛擬化原理探究里面,我們最主要介紹網絡設備IO和塊設備IO,其實他們的原理都很像,但是在虛擬化層又分化開了,這也是為什么網絡設備IO虛擬化和塊設備IO虛擬化要分開講的原因。這一章介紹一下網絡設備IO虛擬化,下一章介紹塊設備IO虛擬化。

傳統的網絡IO流程

這里的傳統并不是真的傳統,而是介紹一下在非虛擬化環境下的網絡設備IO流程。我們平常所使用的Linux版本,比如Debian或者CentOS等都是標準的Linux TCP/IP協議棧,協議棧底層提供了driver抽象層來適配不同的網卡,在虛擬化中最重要的是設備的虛擬化,但是了解整個網絡IO流程后去看待虛擬化就會更加容易理解了。

標準的TCP/IP結構

在用戶層,我們通過socket與Kernel做交互,包括創建端口,數據的接收發送等操作。
在Kernel層,TCP/IP協議棧負責將我們的socket數據封裝到TCP或者UDP包中,然后進入IP層,加入IP地址端口信息等,進入數據鏈路層,加入Mac地址等信息后,通過驅動寫入到網卡,網卡再把數據發送出去。如下圖所示,比較主觀的圖。

KVM 虛擬化原理中的網絡IO虛擬化是怎樣的

在Linux的TCP/IP協議棧中,每個數據包是有內核的skb_buff結構描述的,如下圖所示,socket發送數據包的時候后,進入內核,內核從skb_buff的池中分配一個skb_buff用來承載數據流量。

KVM 虛擬化原理中的網絡IO虛擬化是怎樣的

發送數據和接收數據驅動層都采用DMA模式,驅動加載時候會為網卡映射內存并設置描述狀態(寄存器中),也就是內存的起始位,長度,剩余大小等等。發送時候將數據放到映射的內存中,然后設置網卡寄存器產生一個中斷,告訴網卡有數據,網卡收到中斷后處理對應的內存中的數據,處理完后向CPU產生一個中斷告訴CPU數據發送完成,CPU中斷處理過程中向上層driver通知數據發送完成,driver再依次向上層返回。在這個過程中對于driver來說,發送是同步的。接收數據的流程和發送數據幾乎一致,這里就不細說了。DMA的模式對后面的IO虛擬化來說很重要。

image_1aqger4b915nf19k11gjv1lc21atm9.png-46.6kB

KVM 網絡IO虛擬化

準確來說,KVM只提供了一些基本的CPU和內存的虛擬化方案,真正的IO實現都由qemu-kvm來完成,只不過我們在介紹KVM的文章里都默認qemu-kvm和KVM為一個體系,就沒有分的那么仔細了。實際上網絡IO虛擬化都是由qemu-kvm來完成的。

KVM 全虛擬化IO

還記得我們第一章節的demo里面,我們的“鏡像”調用了 out 指令產生了一個IO操作,然后因為此操作為敏感的設備訪問類型的操作,不能在VMX non-root 模式下執行,于是VM exits,模擬器接管了這個IO操作。

switch (kvm->vcpus->kvm_run->exit_reason) {
        case KVM_EXIT_UNKNOWN:
            printf("KVM_EXIT_UNKNOWN\n");
            break;
        // 虛擬機執行了IO操作,虛擬機模式下的CPU會暫停虛擬機并
        // 把執行權交給emulator
        case KVM_EXIT_IO:
            printf("KVM_EXIT_IO\n");
            printf("out port: %d, data: %d\n", 
                kvm->vcpus->kvm_run->io.port,  
                *(int *)((char *)(kvm->vcpus->kvm_run) + kvm->vcpus->kvm_run->io.data_offset)
                );
            break;
        ...

虛擬機退出并得知原因為 KVM_EXIT_IO,模擬器得知由于設備產生了IO操作并退出,于是獲取這個IO操作并打印出數據。這里其實我們就最小化的模擬了一個虛擬IO的過程,由模擬器接管這個IO。

在qemu-kvm全虛擬化的IO過程中,其實原理也是一樣,KVM捕獲IO中斷,由qemu-kvm接管這個IO,由于采用了DMA映射,qemu-kvm在啟動時候會注冊設備的mmio信息,以便能獲取到DMA設備的映射內存和控制信息。

static int pci_e1000_init(PCIDevice *pci_dev)
{
    e1000_mmio_setup(d); 
    // 為PCI設備設置 mmio 空間
    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 
    pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
    d->nic = qemu_new_nic(&net_e1000_info, &d->conf, object_get_typename(OBJECT(d)), d->dev.qdev.id, d);   
    add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); 
}

對于PCI設備來說,當設備與CPU之間通過映射了一段連續的物理內存后,CPU對PCI設備的訪問只需要像訪問內存一樣訪問既可以。IO設備通常有兩種模式,一種是port模式,一種是MMIO模式,前者就是我們demo里面的in/out指令,后者就是PCI設備的DMA訪問方式,兩種方式的操作都能被KVM捕獲。

于是qemu-kvm將此操作代替Guest完成后并執行相應的“回調”,也就是向vCPU產生中斷告訴IO完成并返回Guest繼續執行。vCPU中斷和CPU中斷一樣,設置相應的寄存器后中斷便會觸發。

在全虛擬化環境下,Guest中的IO都由qemu-kvm接管,在Guest中看到的一個網卡設備并不是真正的一塊網卡,而是由物理機產生的一個tap設備。知識在驅動注冊的時候將一些tap設備所支持的特性加入到了Guest的驅動注冊信息里面,所以在Guest中看到有網絡設備。

KVM 虛擬化原理中的網絡IO虛擬化是怎樣的

如上圖所示,qemu接管了來自Guest的IO操作,真實的場景肯定是需要將數據再次發送出去的,而不是像demo一樣打印出來,在Guest中的數據包二層封裝的Mac地址后,qemu層不需要對數據進行拆開再解析,而只需要將數據寫入到tap設備,tap設備和bridge之間交互完成后,由bridge直接發送到網卡,bridge(其實NIC綁定到了Bridge)開啟了混雜模式,可以將所有請求都接收或者發送出去。

以下來自這篇文章的引用

當一個 TAP 設備被創建時,在 Linux 設備文件目錄下將會生成一個對應 char 設備,用戶程序可以像打開普通文件一樣打開這個文件進行讀寫。當執行 write()操作時,數據進入 TAP 設備,此時對于 Linux 網絡層來說,相當于 TAP 設備收到了一包數據,請求內核接受它,如同普通的物理網卡從外界收到一包數據一樣,不同的是其實數據來自 Linux 上的一個用戶程序。Linux 收到此數據后將根據網絡配置進行后續處理,從而完成了用戶程序向 Linux 內核網絡層注入數據的功能。當用戶程序執行 read()請求時,相當于向內核查詢 TAP 設備上是否有需要被發送出去的數據,有的話取出到用戶程序里,完成 TAP 設備的發送數據功能。針對 TAP 設備的一個形象的比喻是:使用 TAP 設備的應用程序相當于另外一臺計算機,TAP 設備是本機的一個網卡,他們之間相互連接。應用程序通過 read()/write()操作,和本機網絡核心進行通訊。

類似這樣的操作

fd = open("/dev/tap", XXX)
write(fd, buf, 1024);
read(fd, buf, 1024);

bridge可能是一個Linux bridge,也可能是一個OVS(Open virtual switch),在涉及到網絡虛擬化的時候,通常需要利用到bridge提供的VLAN tag功能。

以上就是KVM的網絡全虛擬化IO流程了,我們也可以看到這個流程的不足,比如說當網絡流量很大的時候,會產生過多的VM的切換,同時產生過多的數據copy操作,我們知道copy是很浪費CPU時鐘周期的。于是qemu-kvm在發展的過程中,實現了virtio驅動。

KVM Virtio 驅動

基于 Virtio 的虛擬化也叫作半虛擬化,因為要求在Guest中加入virtio驅動,也就意味著Guest知道了自己運行于虛擬環境了。
KVM 虛擬化原理中的網絡IO虛擬化是怎樣的

vhost-net 繞過了 QEMU 直接在Guest的front-end和backend之間通信,減少了數據的拷貝,特別是減少了用戶態到內核態的拷貝。性能得到大大加強,就吞吐量來說,vhost-net基本能夠跑滿一臺物理機的帶寬。
vhost-net需要內核支持,Redhat 6.1 后開始支持,默認狀態下是開啟的。

KVM的網絡設備IO虛擬化經過了全虛擬化->virtio->vhost-net的進化,性能越來越接近真實物理網卡,但是在小包處理方面任然存在差距,不過已經不是一個系統的瓶頸了,可以看到KVM在經過了這多年的發展后,性能也是越發的強勁,這也是他領先于其他虛擬化的重要原因之一。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

景宁| 福泉市| 安吉县| 剑河县| 阳谷县| 扶风县| 神农架林区| 灵寿县| 抚远县| 湖州市| 南宫市| 青铜峡市| 略阳县| 昭平县| 丰城市| 郎溪县| 南溪县| 新巴尔虎左旗| 额尔古纳市| 喀喇| 凉城县| 纳雍县| 大城县| 株洲市| 邵阳市| 白沙| 白水县| 杂多县| 同心县| 英吉沙县| 阜南县| 贵溪市| 弋阳县| 融水| 营山县| 利川市| 石城县| 如东县| 利辛县| 汉阴县| 周宁县|