日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Linux虛擬化KVM-Qemu分析之Virtqueue

linux虛擬化KVM-Qemu分析之Virtqueue

作者:LoyenWang 2021-03-28 18:23:22

云計算

虛擬化 Virtqueue這種設計思想比較巧妙,不僅用在virtio中,在AMP系統(tǒng)中處理器之間的通信也能看到它的身影。

創(chuàng)新互聯(lián)成立于2013年,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都網(wǎng)站建設、做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元息縣做網(wǎng)站,已為上家服務,為息縣各地企業(yè)和個人服務,聯(lián)系電話:13518219792

 [[390061]]

本文轉載自微信公眾號「LoyenWang」,作者LoyenWang。轉載本文請聯(lián)系LoyenWang公眾號。

背景

  • Read the fucking source code! --By 魯迅
  • A picture is worth a thousand words. --By 高爾基

說明:

  1. KVM版本:5.9.1
  2. QEMU版本:5.0.0
  3. 工具:Source Insight 3.5, Visio
  4. 文章同步在博客園:https://www.cnblogs.com/LoyenWang/

1. 概述

汪汪汪,最近忙成狗了,一下子把我更新的節(jié)奏打亂了,草率的道個歉。

  • 前邊系列將Virtio Device和Virtio Driver都已經(jīng)講完,本文將分析virtqueue;
  • virtqueue用于前后端之間的數(shù)據(jù)交換,一看到這種數(shù)據(jù)隊列,首先想到的就是ring-buffer,實際的實現(xiàn)會是怎么樣的呢?

2. 數(shù)據(jù)結構

先看一下核心的數(shù)據(jù)結構:

  • 通常Virtio設備操作Virtqueue時,都是通過struct virtqueue結構體,這個可以理解成對外的一個接口,而Virtqueue機制的實現(xiàn)依賴于struct vring_virtqueue結構體;
  • Virtqueue有三個核心的數(shù)據(jù)結構,由struct vring負責組織:
  1. struct vring_desc:描述符表,每一項描述符指向一片內(nèi)存,內(nèi)存類型可以分為out類型和in類型,分別代表輸出和輸入,而內(nèi)存的管理都由驅動來負責。該結構體中的next字段,可用于將多個描述符構成一個描述符鏈,而flag字段用于描述屬性,比如只讀只寫等;
  2. struct vring_avail:可用描述符區(qū)域,用于記錄設備可用的描述符ID,它的主體是數(shù)組ring,實際就是一個環(huán)形緩沖區(qū);
  3. struct vring_used:已用描述符區(qū)域,用于記錄設備已經(jīng)處理完的描述符ID,同樣,它的ring數(shù)組也是環(huán)形緩沖區(qū),與struct vring_avail不同的是,它還記錄了設備寫回的數(shù)據(jù)長度;

這么看,當然是有點不太直觀,所以,下圖來了:

  • 簡單來說,驅動會分配好內(nèi)存(scatterlist),并通過virtqueue_add添加到描述表中,這樣描述符表中的條目就都能對應到具體的物理地址了,其實可以把它理解成一個資源池子;
  • 驅動可以將可用的資源更新到struct vring_avail中,也就是將可用的描述符ID添加到ring數(shù)組中,熟悉環(huán)形緩沖區(qū)的同學應該清楚它的機制,通過維護頭尾兩個指針來進行管理,Driver負責更新頭指針(idx),Device負責更新尾指針(Qemu中的Device負責維護一個last_avail_idx),頭尾指針,你追我趕,生生不息;
  • 當設備使用完了后,將已用的描述符ID更新到struct vring_used中,vring_virtqueue自身維護了last_used_idx,機制與struct vring_avail一致;

3. 流程分析

3.1 發(fā)送

當驅動需要把數(shù)據(jù)發(fā)送給設備時,流程如上圖所示:

①A表示分配一個Buffer并添加到Virtqueue中,①B表示從Used隊列中獲取一個Buffer,這兩種中選擇一種方式;

②表示將Data拷貝到Buffer中,用于傳送;

③表示更新Avail隊列中的描述符索引值,注意,驅動中需要執(zhí)行memory barrier操作,確保Device能看到正確的值;

④與⑤表示Driver通知Device來取數(shù)據(jù);

⑥表示Device從Avail隊列中獲取到描述符索引值;

⑦表示將描述符索引對應的地址中的數(shù)據(jù)取出來;

⑧表示Device更新Used隊列中的描述符索引;

⑨與⑩表示Device通知Driver數(shù)據(jù)已經(jīng)取完了;

3.2 接收

當驅動從設備接收數(shù)據(jù)時,流程如上圖所示:

①表示Device從Avail隊列中獲取可用描述符索引值;

②表示將數(shù)據(jù)拷貝至描述符索引對應的地址上;

③表示更新Used隊列中的描述符索引值;

④與⑤表示Device通知Driver來取數(shù)據(jù);

⑥表示Driver從Used隊列中獲取已用描述符索引值;

⑦表示將描述符索引對應地址中的數(shù)據(jù)取出來;

⑧表示將Avail隊列中的描述符索引值進行更新;

⑨與⑩表示Driver通知Device有新的可用描述符;

3.3 代碼分析

代碼的分析將圍繞下邊這個圖來展開(Virtio-Net),偷個懶,只分析單向數(shù)據(jù)發(fā)送了:

3.3.1 virtqueue創(chuàng)建

  • 之前的系列文章分析過virtio設備和驅動,Virtio-Net是PCI網(wǎng)卡設備驅動,分別會在virtnet-probe和virtio_pci_probe中完成所有的初始化;
  • virtnet_probe函數(shù)入口中,通過init_vqs完成Virtqueue的初始化,這個逐級調(diào)用關系如圖所示,最終會調(diào)用到vring_create_virtqueue來創(chuàng)建Virtqueue;
  • 這個創(chuàng)建的過程中,有些細節(jié)是忽略的,比如通過PCI去讀取設備的配置空間,獲取創(chuàng)建Virtqueue所需要的信息等;
  • 最終就是圍繞vring_virtqueue數(shù)據(jù)結構的初始化展開,其中vring數(shù)據(jù)結構的內(nèi)存分配也都是在驅動中完成,整個結構體都由驅動來管理與維護;

3.3.2 virtio-net驅動發(fā)送

  • 網(wǎng)絡數(shù)據(jù)的傳輸在驅動中通過start_xmit函數(shù)來實現(xiàn);
  • xmit_skb函數(shù)中,sg_init_table初始化sg列表,sg_set_buf將sg指向特定的buffer,skb_to_sgvec將socket buffer中的數(shù)據(jù)填充sg;
  • 通過virtqueue_add_outbuf將sg添加到Virtqueue中,并更新Avail隊列中描述符的索引值;
  • virtqueue_notify通知Device,可以過來取數(shù)據(jù)了;

3.3.3 Qemu virtio-net設備接收

  • Guest驅動寫寄存器操作時,陷入到KVM中,最終Qemu會捕獲到進行處理,入口函數(shù)為kvm_handle_io;
  • Qemu中會針對IO內(nèi)存區(qū)域設置讀寫的操作函數(shù),當Guest進行IO操作時,最終觸發(fā)操作函數(shù)的調(diào)用,針對Virtio-Net,由于它是PCI設備,操作函數(shù)為virtio_pci_config_write;
  • virtio_pci_config_write函數(shù)中,對Guest的寫操作進行判斷并處理,比如在VIRTIO_PCI_QUEUE_NOTIFY時,調(diào)用virtio_queue_notify,用于處理Guest驅動的通知,并最終回調(diào)handle_output函數(shù);
  • 針對Virtio-Net設備,發(fā)送的回調(diào)函數(shù)為virtio_net_handle_tx_bh,并在virtio_net_flush_tx中完成操作;
  • 通用的操作模型:通過virtqueue_pop從Avail隊列中獲取地址,將數(shù)據(jù)進行處理,通過virtqueue_push將處理完后的描述符索引更新到Used隊列中,通過virtio_notify通知Guest驅動;
  • Virtqueue這種設計思想比較巧妙,不僅用在virtio中,在AMP系統(tǒng)中處理器之間的通信也能看到它的身影。

草草收場了,下回見。

參考

https://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels

Virtual I/O Device Version 1.1


新聞名稱:Linux虛擬化KVM-Qemu分析之Virtqueue
網(wǎng)頁鏈接:http://www.dlmjj.cn/article/coohcgg.html