您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)virtio驅(qū)動(dòng)是如何同設(shè)備交互 ,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
irtio是對(duì)虛擬化環(huán)境下guest kernel中io操作的一種優(yōu)化。
首先需要說(shuō)明的是,在內(nèi)核的角度來(lái)看,virtio設(shè)備及其driver,和其他設(shè)備及驅(qū)動(dòng)一樣,都是普通的設(shè)備,并沒(méi)有什么特殊性。也就是說(shuō),內(nèi)核并不知道這種io優(yōu)化的存在。
virtio設(shè)備,在系統(tǒng)層面看,就是pci設(shè)備。但是,為了提高io效率,對(duì)io操作做出了優(yōu)化。
主要方案是:
1) 當(dāng)virtio設(shè)備輸出數(shù)據(jù)時(shí),driver將數(shù)據(jù)送到buffer隊(duì)列中(從virtio網(wǎng)卡驅(qū)動(dòng)的代碼來(lái)看,此操作無(wú)內(nèi)存拷貝,直接將數(shù)據(jù)所占的內(nèi)存 作為buffer添加到隊(duì)列中就完成了),然后通過(guò)io指令寫(xiě)設(shè)備寄存器(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY),以通知虛擬機(jī)系統(tǒng)(kvm+qemu)。虛擬機(jī)系統(tǒng)捕獲了io指令,就得到了通知,從buffer隊(duì) 列中獲取設(shè)備輸出的數(shù)據(jù)。
2) 當(dāng)需要向virtio設(shè)備輸入數(shù)據(jù)時(shí),虛擬機(jī)系統(tǒng)將數(shù)據(jù)送到buffer隊(duì)列中,然后觸發(fā)設(shè)備中斷。driver收到中斷后,直接從隊(duì)列中取出數(shù)據(jù)即可 (從virtio網(wǎng)卡驅(qū)動(dòng)的代碼來(lái)看,隊(duì)列中的數(shù)據(jù)已經(jīng)不需要再進(jìn)行內(nèi)存拷貝,隊(duì)列中的數(shù)據(jù)已經(jīng)是sk_buff結(jié)構(gòu)了)。
從上面的機(jī)制來(lái)看,virtio并不是完全沒(méi)有了io操作。例如,設(shè)備輸出數(shù)據(jù)時(shí),在將數(shù)據(jù)送入buffer隊(duì)列后,還是執(zhí)行了io操作,以通知虛擬機(jī)系統(tǒng)。但是,這個(gè)io操作,并不是將輸出數(shù)據(jù)寫(xiě)入設(shè)備,而是將數(shù)據(jù)已入隊(duì)這件事,寫(xiě)入設(shè)備。
以上是virtio的大體原理。下面來(lái)看看virtio的設(shè)計(jì)思路。
大體分如下4個(gè)層次。
一、buffer隊(duì)列
既然virtio通過(guò)buffer隊(duì)列實(shí)現(xiàn)設(shè)備輸入輸出。那么,如果每一種設(shè)備都來(lái)實(shí)現(xiàn)一下buffer隊(duì)列,不是浪費(fèi)么?沒(méi)錯(cuò),virtio考慮到這個(gè) 共性需求,因此就實(shí)現(xiàn)一個(gè)共同的buffer隊(duì)列模塊——virtio_ring(一個(gè)環(huán)型隊(duì)列)。但是,如果哪天buffer隊(duì)列的實(shí)現(xiàn),需要重新設(shè)計(jì) 怎么辦?考慮到這一點(diǎn),再對(duì)buffer隊(duì)列的操作包裝出一個(gè)抽象層——struct virtqueue_ops。每一種buffer隊(duì)列的實(shí)現(xiàn),只要提供一個(gè)virtqueue_ops結(jié)構(gòu)變量給用戶(hù)使用即可。這就實(shí)現(xiàn)了隊(duì)列操作與隊(duì)列 實(shí)現(xiàn)的解耦。
struct virtqueue_ops
{
int (*add_buf)(struct virtqueue *vq,
struct scatterlist sg[],
unsigned int out_num,
unsigned int in_num,
void *data);
void (*kick)(struct virtqueue *vq);
void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
void (*disable_cb)(struct virtqueue *vq);
bool (*enable_cb)(struct virtqueue *vq);
};
二、pci層
每一個(gè)virtio設(shè)備(例如:塊設(shè)備或網(wǎng)卡),在系統(tǒng)層面看來(lái),都是一個(gè)pci設(shè)備。這些設(shè)備之間,有共性部分,也有差異部分。
1)共性部分:這些設(shè)備都需要掛接相應(yīng)的buffer隊(duì)列操作virtqueue_ops,都需要申請(qǐng)若干個(gè)buffer隊(duì)列,當(dāng)執(zhí)行io輸出時(shí),需要向 隊(duì)列寫(xiě)入數(shù)據(jù);都需要執(zhí)行pci_iomap將設(shè)備配置寄存器區(qū)間映射到內(nèi)存區(qū)間;都需要設(shè)置中斷處理;等中斷來(lái)了,都需要從隊(duì)列讀出數(shù)據(jù),并通知虛擬機(jī) 系統(tǒng),數(shù)據(jù)已入隊(duì)。
2) 差異部分:設(shè)備中系統(tǒng)中,如何與業(yè)務(wù)關(guān)聯(lián)起來(lái)。各個(gè)設(shè)備不相同。例如,網(wǎng)卡在內(nèi)核中是一個(gè)net_device,與協(xié)議棧系統(tǒng)關(guān)聯(lián)起來(lái)。同時(shí),向隊(duì)列中寫(xiě)入什么數(shù)據(jù),數(shù)據(jù)的含義如何,各個(gè)設(shè)備不相同。隊(duì)列中來(lái)了數(shù)據(jù),是什么含義,如何處理,各個(gè)設(shè)備不相同。
如果每個(gè)virtio設(shè)備都完整實(shí)現(xiàn)自己的功能,又會(huì)形成浪費(fèi)。
針對(duì)這個(gè)現(xiàn)象,virtio又設(shè)計(jì)了virtio_pci模塊,以處理所有virtio設(shè)備的共性部分。這樣一來(lái),所有的virtio設(shè)備,在系統(tǒng)層面看來(lái),都是一個(gè)pci設(shè)備,其設(shè)備驅(qū)動(dòng)都是virtio_pci。
但是,virtio_pci并不能完整的驅(qū)動(dòng)任何一個(gè)設(shè)備。因此,virtio_pci在probe(接管)每一個(gè)設(shè)備時(shí),根據(jù)每個(gè)pci設(shè)備的 subsystem vendor/device id來(lái)識(shí)別出這具體是哪一種virtio設(shè)備,然后相應(yīng)的向內(nèi)核注冊(cè)一個(gè)virtio設(shè)備。當(dāng)然,在注冊(cè)virtio設(shè)備之前,virtio_pci驅(qū)動(dòng) 已經(jīng)為此設(shè)備做了諸多共性的操作。同時(shí),還為設(shè)備提供了各種操作的適配接口,例如,一些常用的pci設(shè)備操作,還有申請(qǐng)buffer隊(duì)列的操作。這些操 作,都通過(guò)virtio_config_ops結(jié)構(gòu)變量來(lái)適配。
三、virtio驅(qū)動(dòng)
這里講virtio驅(qū)動(dòng),指的是具體的各個(gè)設(shè)備的驅(qū)動(dòng)了。例如,網(wǎng)卡或塊設(shè)備。有了前面所述的各模塊的工作,virtio各個(gè)設(shè)備的驅(qū)動(dòng)實(shí)現(xiàn),就相對(duì)簡(jiǎn)單了。大體來(lái)說(shuō),除了完成本設(shè)備特有的功能以外,剩下的基本就是buffer隊(duì)列相關(guān)操作了。
那就是申請(qǐng)幾個(gè)隊(duì)列,并提供相應(yīng)的回調(diào)函數(shù)。有數(shù)據(jù)要輸出,往隊(duì)列中送就行了。隊(duì)列來(lái)數(shù)據(jù)了,自然會(huì)有中斷產(chǎn)生,中斷處理中,自然會(huì)觸發(fā)回調(diào)來(lái)處理。
四、virtio_bus
內(nèi)核中的各種對(duì)象,總是有秩序的。為了管理每種具體的virtio驅(qū)動(dòng)及每個(gè)具體的virtio設(shè)備,干脆搞了一個(gè)virtio_bus出來(lái)。當(dāng)然,這個(gè) bus并不存在實(shí)際的硬件電路,純粹起個(gè)管理與適配作用。就這個(gè)管理與適配功能而言,他和pci總線是相似的。全部的virtio driver與virtio device,在virtio_bus中都能夠找到。每當(dāng)有新的virtio driver或者virtio device注冊(cè)到系統(tǒng)中時(shí),系統(tǒng)都會(huì)執(zhí)行一次設(shè)備與驅(qū)動(dòng)的匹配操作。
關(guān)于virtio驅(qū)動(dòng)是如何同設(shè)備交互 就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。