最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

深入分析Linux虛擬化KVM-Qemu之ioeventfd與irqfd

2023-02-28 20:52 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

說明:

  1. KVM版本:5.9.1

  2. QEMU版本:5.0.0

  3. 工具:Source Insight 3.5, Visio

1. 概述

  • 圖中的各個(gè)模塊,只剩下通知機(jī)制沒講了,本文來一篇終結(jié)者;

Guest與KVM及Qemu之間的通知機(jī)制,如下圖:

  • irqfd:提供一種機(jī)制,可以通過文件描述fd來向Guest注入中斷,路徑為紫色線條所示;

  • ioeventfd:提供一種機(jī)制,可以通過文件描述符fd來接收Guest的信號,路徑為紅色線條所示;

  • eventfdirqfd這兩種機(jī)制,都是基于eventfd來實(shí)現(xiàn)的;

本文會先介紹eventfd機(jī)制,然后再分別從Qemu/KVM來介紹ioeventfdirqfd,開始吧。

2. eventfd

? 說來很巧,我曾經(jīng)在工作中實(shí)現(xiàn)過一個(gè)類似eventfd機(jī)制的內(nèi)核模塊,用于多線程之間的輕量級通知,算是重復(fù)造輪子了。

eventfd的機(jī)制比較簡單,大體框架如下圖:

  • 內(nèi)核中創(chuàng)建了一個(gè)struct eventfd_ctx結(jié)構(gòu)體,該結(jié)構(gòu)體中維護(hù)一個(gè)count計(jì)數(shù),以及一個(gè)等待隊(duì)列頭;

  • 線程/進(jìn)程在讀eventfd時(shí),如果count值等于0時(shí),將當(dāng)前任務(wù)添加到等待隊(duì)列中,并進(jìn)行調(diào)度,讓出CPU。讀過程count值會進(jìn)行減操作;

  • 線程/進(jìn)程在寫eventfd時(shí),如果count值超過最大值時(shí),會將當(dāng)前任務(wù)添加到等待隊(duì)列中(特殊情況),寫過程count值會進(jìn)行加操作,并喚醒在等待隊(duì)列上的任務(wù);

  • 內(nèi)核的其他模塊也可以通過eventfd_signal接口,將count值加操作,并喚醒在等待隊(duì)列上的任務(wù);

代碼實(shí)現(xiàn)如下圖:

  • eventfd機(jī)制對用戶層提供的系統(tǒng)調(diào)用接口包括eventfd()write(),read()select/poll等;

  • 通過eventfd來創(chuàng)建文件描述符,從代碼中可以看出,該接口的實(shí)現(xiàn)為do_eventfd,完成的工作包括:

1)在內(nèi)核中分配struct eventfd_ctx結(jié)構(gòu)體來維護(hù)上下文;

2)初始化等待隊(duì)列頭用于存放睡眠等待的任務(wù);

3)分配未使用的文件描述符fd,創(chuàng)建file實(shí)例(該實(shí)例會綁定操作函數(shù)集),將文件描述符fd與file實(shí)例建立連接等;

? 最終系統(tǒng)調(diào)用read/write時(shí),便會分別調(diào)用到eventfd_read/eventfd_write函數(shù):

  • eventfd_read:如果count值為0,將自身添加到等待隊(duì)列中,設(shè)置任務(wù)的狀態(tài)后調(diào)用schedule讓出CPU,等待被喚醒。讀操作中會對count值進(jìn)行減操作,最后再判斷等待隊(duì)列中是否有任務(wù),有則進(jìn)行喚醒;

  • eventfd_write:判斷count值在增加ucnt后是否會越界,越界則將自身添加到等待隊(duì)列中,設(shè)置任務(wù)的狀態(tài)后調(diào)用schedule讓出CPU,等待被喚醒。寫操作會對count值進(jìn)行加操作,最后再判斷等待隊(duì)列中是否有任務(wù),有則進(jìn)行喚醒;

  • 此外,還有eventfd_signal接口,比較簡單,完成的工作就是對count值進(jìn)行加操作,并喚醒等待任務(wù);

基石講完了,我們來看看基于之上的ioeventfdirqfd。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ?


3. ioeventfd

3.1 Qemu側(cè)

以PCI設(shè)備為例:

  • Qemu中模擬PCI設(shè)備時(shí),在初始化過程中會調(diào)用memory_region_init_io來進(jìn)行IO內(nèi)存空間初始化,這個(gè)過程中會綁定內(nèi)存區(qū)域的回調(diào)函數(shù)集,當(dāng)Guest OS訪問這個(gè)IO區(qū)域時(shí),可能觸發(fā)這些回調(diào)函數(shù)的調(diào)用;

  • Guest OS中的Virtio驅(qū)動配置完成后會將狀態(tài)位置上VIRTIO_CONFIG_S_DRIVER_OK,此時(shí)Qemu中的操作函數(shù)調(diào)用virtio_pci_common_write,并按圖中的調(diào)用流逐級往下;

  • event_notifier_init:完成eventfd的創(chuàng)建工作,它實(shí)際上就是調(diào)用系統(tǒng)調(diào)用eventfd()的接口,得到對應(yīng)的文件描述符;

  • memory_region_add_eventfd:為內(nèi)存區(qū)域添加eventfd,將eventfd和對應(yīng)的內(nèi)存區(qū)域關(guān)聯(lián)起來;

? 看一下memory_region_add_eventfd的流程:

  • 內(nèi)存區(qū)域MemoryRegion中的ioeventfds成員按照地址從小到大排序,memory_region_add_eventfd函數(shù)會選擇合適的位置將ioeventfds插入,并提交更新;

  • 提交更新過程中最終觸發(fā)回調(diào)函數(shù)kvm_mem_ioeventfd_add的執(zhí)行,這個(gè)函數(shù)指針的初始化是在Qemu進(jìn)行kvm_init時(shí),針對不同類型的內(nèi)存區(qū)域注冊了對應(yīng)的memory_listener用于監(jiān)聽變化;

  • kvm_vm_ioctl:向KVM注冊ioeventfd

Qemu中完成了初始化后,任務(wù)就轉(zhuǎn)移到了KVM中。

3.2 KVM側(cè)

KVM中的ioeventfd注冊如下:

  • KVM中注冊ioeventfd的核心函數(shù)為kvm_assign_ioeventfd_idx,該函數(shù)中主要工作包括:

1)根據(jù)用戶空間傳遞過來的fd獲取到內(nèi)核中對應(yīng)的struct eventfd_ctx結(jié)構(gòu)體上下文;2)使用ioeventfd_ops操作函數(shù)集來初始化IO設(shè)備操作;3)向KVM注冊IO總線,比如KVM_MMIO_BUS,注冊了一段IO地址區(qū)域,當(dāng)操作這段區(qū)域的時(shí)候出發(fā)對應(yīng)的操作函數(shù)回調(diào);

  • 當(dāng)Guest OS中進(jìn)行IO操作時(shí),觸發(fā)VM異常退出,KVM進(jìn)行捕獲處理,最終調(diào)用注冊的ioevnetfd_write,在該函數(shù)中調(diào)用eventfd_signal喚醒阻塞在eventfd上的任務(wù),Qemu和KVM完成了閉環(huán);

總體效果如下圖:

4. irqfd

Qemu和KVM中的流程如下圖:

  • Qemu中通過kvm_irqchip_assign_irqfd向KVM申請注冊irqfd

  • 在KVM中,內(nèi)核通過維護(hù)struct kvm_kernel_irqfd結(jié)構(gòu)體來管理整個(gè)irqfd的流程;

  • kvm_irqfd_assign

1)分配struct kvm_kernel_irqfd結(jié)構(gòu)體,并進(jìn)行各個(gè)字段的初始化;2)初始化工作隊(duì)列任務(wù),設(shè)置成irqfd_inject,用于向Guest OS注入虛擬中斷;3)初始化等待隊(duì)列的喚醒函數(shù),設(shè)置成irqfd_wakeup,當(dāng)任務(wù)被喚醒時(shí)執(zhí)行,在該函數(shù)中會去調(diào)度工作任務(wù)irqfd_inject;4)初始化pll_table pt字段的處理函數(shù),設(shè)置成irqfd_ptable_queue_proc,該函數(shù)實(shí)際是調(diào)用add_wait_queue將任務(wù)添加至eventfd的等待隊(duì)列中,這個(gè)過程是在vfs_poll中完成的;

  • 當(dāng)Qemu通過irqfd機(jī)制發(fā)送信號時(shí),將喚醒睡眠在eventfd上的任務(wù),喚醒后執(zhí)行irqfd_wakeup函數(shù),在該函數(shù)中調(diào)度任務(wù),調(diào)用irqfd_inject來注入中斷;

總體效果如下圖:


原文作者:LoyenWang




深入分析Linux虛擬化KVM-Qemu之ioeventfd與irqfd的評論 (共 條)

使用qq登录你需要登录后才可以评论。
峨边| 龙川县| 电白县| 吉木萨尔县| 芒康县| 翁牛特旗| 中西区| 夏邑县| 靖江市| 无锡市| 太康县| 克东县| 灌云县| 连江县| 潍坊市| 乐安县| 尤溪县| 长汀县| 凤凰县| 桦南县| 横峰县| 大余县| 正阳县| 桃园县| 田阳县| 行唐县| 达州市| 天长市| 岢岚县| 平江县| 前郭尔| 荥阳市| 香格里拉县| 松溪县| 永和县| 洛阳市| 龙陵县| 三河市| 凤翔县| 准格尔旗| 新乐市|