女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

linux設(shè)備中virtio組織關(guān)系及設(shè)備初始化調(diào)用流程

454398 ? 來(lái)源: Chinaunix ? 作者:lvyilong316 ? 2020-09-25 15:47 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

我們看linux kernel中virtio驅(qū)動(dòng)相關(guān)代碼,會(huì)發(fā)現(xiàn)有很多相關(guān)文件。首先有virtio.c這種文件,其次還有virtio_pci.c,virtio_scsi.c等這些文件,還有virtio_net.c,virtio_blk.c,virtio_balloon.c等這些。那么這些文件是什么關(guān)系呢?其次里面很多還有各自probe函數(shù),到底是如何調(diào)用的,例如以網(wǎng)絡(luò)的virtio_net到底是從哪里開(kāi)始初始化的?要理清這些關(guān)系需要以linux設(shè)備驅(qū)動(dòng)模型為背景展開(kāi)討論。這篇文章,我們以linux kernel 3.10代碼為例,分析一下virtio的相關(guān)組織關(guān)系,以及設(shè)備初始化調(diào)用流程。

總線及驅(qū)動(dòng)的注冊(cè)

linux設(shè)備驅(qū)動(dòng)模型的核心有三個(gè)概念:設(shè)備(device),驅(qū)動(dòng)(driver),總線(bus)。而如果我們把virtio的相關(guān)關(guān)系梳理清楚后,以網(wǎng)絡(luò)virtio_net為例映射到設(shè)備驅(qū)動(dòng)模型,就得到了下圖。我們這個(gè)小節(jié)后面就以下圖為背景展開(kāi)。

圖1

linux將virtio實(shí)現(xiàn)分離成兩部分:和物理總線標(biāo)準(zhǔn)相關(guān)的(如pci,scsi等),和物理總線標(biāo)準(zhǔn)無(wú)關(guān)的。

圖中左側(cè)部分即和物理總線相關(guān)的實(shí)現(xiàn),這里以pci為了,當(dāng)然virtio也支持其他總線類型,如scsi。virtio-pci是virtio對(duì)應(yīng)pci的驅(qū)動(dòng)實(shí)現(xiàn),所以virtio-pci是一個(gè)pci總線上的一個(gè)驅(qū)動(dòng)。它通過(guò)如下方式注冊(cè)到pci總線上去。

lvirtio總線的注冊(cè)

點(diǎn)擊(此處)折疊或打開(kāi)

/*virtio.c*/

static struct bus_type virtio_bus={

.name="virtio",

.match=virtio_dev_match,

.dev_attrs=virtio_dev_attrs,

.uevent=virtio_uevent,

.probe=virtio_dev_probe,

.remove=virtio_dev_remove,

};

staticintvirtio_init(void)

{

if(bus_register(&virtio_bus)!=0)

panic("virtio bus registration failed");

return 0;

}

core_initcall(virtio_init);

如代碼所示,這個(gè)總線的名字叫”virtio”,通過(guò)bus_register就將virtio總線注冊(cè)進(jìn)系統(tǒng),可以在sys文件系統(tǒng)中查看。

lvirtio-net驅(qū)動(dòng)注冊(cè)

最后我們看我們經(jīng)常接觸到設(shè)備驅(qū)動(dòng)的初始化,我們以網(wǎng)絡(luò)驅(qū)動(dòng)virtio_net為例,其對(duì)應(yīng)的驅(qū)動(dòng)為virtio-net。其注冊(cè)過(guò)程如下。

點(diǎn)擊(此處)折疊或打開(kāi)

/*virtio-net.c*/

static struct virtio_device_id id_table[]={

{VIRTIO_ID_NET,VIRTIO_DEV_ANY_ID},

{0},

};

static struct virtio_driver virtio_net_driver={

.feature_table=features,

.feature_table_size=ARRAY_SIZE(features),

.driver.name=KBUILD_MODNAME,

.driver.owner=THIS_MODULE,

.id_table=id_table,

.probe=virtnet_probe,

.remove=virtnet_remove,

.config_changed=virtnet_config_changed,

#ifdef CONFIG_PM

.freeze=virtnet_freeze,

.restore=virtnet_restore,

#endif

};

module_virtio_driver(virtio_net_driver);

#define module_virtio_driver(__virtio_driver)\

module_driver(__virtio_driver,register_virtio_driver,\

unregister_virtio_driver)

intregister_virtio_driver(struct virtio_driver*driver)

{

/*Catch this early.*/

BUG_ON(driver->feature_table_size&&!driver->feature_table);

driver->driver.bus=&virtio_bus;

return driver_register(&driver->driver);

}

最終通過(guò)register_virtio_driver函數(shù)將驅(qū)動(dòng)的bus設(shè)置為之前注冊(cè)的virtio總線,完成總線的注冊(cè)。這樣我們就能在sys文件系統(tǒng)對(duì)應(yīng)virtio總線下的drivers目錄看到這個(gè)驅(qū)動(dòng)了。

所以我們?cè)倩仡^來(lái)看圖1,可以看到virtio設(shè)備是橫跨兩類總線及驅(qū)動(dòng)的。

virtio設(shè)備的初始化流程

梳理清楚virtio相關(guān)設(shè)備,總線及驅(qū)動(dòng)關(guān)系后我們看下virtio設(shè)備的初始化過(guò)程,我們還是以網(wǎng)絡(luò)virtio_net設(shè)備為例子。這個(gè)初始化過(guò)程如下圖2中的黃色部分所示。

圖2

首先是系統(tǒng)啟動(dòng)kernel初始化階段,pci子系統(tǒng)調(diào)用pci_scan_device發(fā)現(xiàn)pci網(wǎng)卡設(shè)備,并初始化對(duì)應(yīng)pci_dev結(jié)構(gòu),然后將去注冊(cè)到pci總線上(dev->dev.bus=&pci_bus_type)。同時(shí)設(shè)置devicevendor_id0x1AF4virtiopci vendor_id,device_id為1

然后當(dāng)我們加載virtio-pci驅(qū)動(dòng)時(shí),當(dāng)調(diào)用module_pci_driver(virtio_pci_driver)將virtio-pci驅(qū)動(dòng)注冊(cè)在pci總線上時(shí),在linux設(shè)備驅(qū)動(dòng)模型中,這會(huì)導(dǎo)致對(duì)pci總線設(shè)備鏈表上未被驅(qū)動(dòng)綁定的每個(gè)設(shè)備調(diào)用pci總線的match回調(diào)函數(shù),即pci_bus_match函數(shù)。原型如下:

static int pci_bus_match(struct device *dev, struct device_driver *drv)

pci_bus_match函數(shù)將linux設(shè)備驅(qū)動(dòng)模型核心出入的device結(jié)構(gòu)轉(zhuǎn)換為pci_dev結(jié)構(gòu),將device_driver結(jié)構(gòu)轉(zhuǎn)換為pci_driver結(jié)構(gòu),之后調(diào)用pci_match_device函數(shù)判斷pci設(shè)備結(jié)構(gòu)是否有匹配的pci設(shè)備ID結(jié)構(gòu)。如果有則判斷設(shè)備的pci ID和驅(qū)動(dòng)設(shè)置的id_table中是否一樣,如果一樣說(shuō)明設(shè)備和驅(qū)動(dòng)匹配(這里設(shè)備的vendor_id和virtio-pci的virtio_pci_id_table匹配),將struct device的driver指針指向驅(qū)動(dòng),然后調(diào)用pci總線的probe函數(shù),即pci_deivce_probe函數(shù)。這個(gè)函數(shù)再次將struct device強(qiáng)制轉(zhuǎn)換成struct pci_dev,將設(shè)置在設(shè)備中的driver結(jié)構(gòu)強(qiáng)制轉(zhuǎn)換為struct pci_derver。它再次校驗(yàn)這個(gè)驅(qū)動(dòng)能否支持這個(gè)設(shè)備,遞增設(shè)備的引用計(jì)數(shù),然后調(diào)用pci驅(qū)動(dòng)probe函數(shù)(即virtio-pci的probe函數(shù)virtio_pci_probe),傳入它應(yīng)該綁定到的struct pci_dev結(jié)構(gòu)體指針。這就進(jìn)入到了圖2中黃色部分的函數(shù)調(diào)用鏈了。

在開(kāi)始梳理virtio_net初始化調(diào)用鏈前我們先看其對(duì)應(yīng)的結(jié)構(gòu)struct virtio_pci_device,將其展開(kāi)得到圖3。

圖3

我們看到virtio_pci_device可以分為兩部分,一部分是和pci總線相關(guān)的設(shè)備對(duì)應(yīng)struct pci_dev,另一部分是和virtio總線相關(guān)的設(shè)備對(duì)應(yīng)structvirtio_device。

virtio_pci_probe函數(shù)主要負(fù)責(zé)完成pci_dev部分的初始化,已經(jīng)virtio_device部分初始化,然后調(diào)用register_virtio_device函數(shù)。

register_virtio_device函數(shù)將virtio_device的設(shè)備總線設(shè)置為virtio總線,然后調(diào)用device_register將virtio_device對(duì)應(yīng)的設(shè)備添加到virtio總線上。這個(gè)添加總線的動(dòng)作,會(huì)觸發(fā)virtio總線的match函數(shù)即virtio_dev_match調(diào)用,同樣該函數(shù)會(huì)比較設(shè)備dev的pci id和驅(qū)動(dòng)id (virtio net的devid為1),如果匹配則virtio bus的probe函數(shù)virtio_dev_probe將被調(diào)用。其中又會(huì)調(diào)用對(duì)應(yīng)驅(qū)動(dòng)的probe函數(shù),即virtnet_probe。而virtnet_probe將會(huì)完成virtio net設(shè)備structvirtio_device剩余部分的初始化。

到此,virtio net的初始化流程就已經(jīng)梳理清楚了。virtio net設(shè)備創(chuàng)建完成后也會(huì)分別出現(xiàn)在pci總線和virtio總線的drvices目錄下。

最后附上virtio的其他類型設(shè)備id:

點(diǎn)擊(此處)折疊或打開(kāi)

#define VIRTIO_ID_NET1/*virtio net*/

#define VIRTIO_ID_BLOCK2/*virtio block*/

#define VIRTIO_ID_CONSOLE3/*virtio console*/

#define VIRTIO_ID_RNG4/*virtio rng*/

#define VIRTIO_ID_BALLOON5/*virtio balloon*/

#define VIRTIO_ID_RPMSG7/*virtio remote processor messaging*/

#define VIRTIO_ID_SCSI8/*virtio scsi*/

#define VIRTIO_ID_9P9/*9p virtio console*/

#define VIRTIO_ID_RPROC_SERIAL 11/*virtio remoteproc seriallink*/

#define VIRTIO_ID_CAIF 12/*Virtio caif*/

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11509

    瀏覽量

    213715
  • 總線
    +關(guān)注

    關(guān)注

    10

    文章

    2959

    瀏覽量

    89729
  • 設(shè)備驅(qū)動(dòng)

    關(guān)注

    0

    文章

    68

    瀏覽量

    11137
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    【明天會(huì)更好】關(guān)于應(yīng)屆畢業(yè)生檔案、戶口、party組織關(guān)系...

    關(guān)于應(yīng)屆畢業(yè)生檔案、戶口、party組織關(guān)系的問(wèn)題:作為過(guò)來(lái)人,我覺(jué)得應(yīng)屆畢業(yè)生檔案、戶口、party組織關(guān)系等這些問(wèn)題必須得自己搞清楚了。不然有你吃虧的一天呀!{:soso_e116:}
    發(fā)表于 05-14 16:52

    c語(yǔ)言編程多個(gè)文件的組織關(guān)系錯(cuò)誤

    c語(yǔ)言編程多個(gè)文件的組織關(guān)系錯(cuò)誤 因?yàn)閗eyboard.c,display.c需要reg52.h,為皮面重定義我建了reg.h中有:#include 已知:main.c: #include
    發(fā)表于 06-15 14:51

    如何初始化函數(shù)? 如何從代碼配置器調(diào)用函數(shù)?

    :V3.30XC8:V1.37 OS:Mac OS 1011區(qū)域:如何初始化函數(shù)和調(diào)用函數(shù)?設(shè)備:PIC16F1847外圍設(shè)備:EASART,ADCMOD:異步
    發(fā)表于 10-15 09:38

    處理器和PCH設(shè)備之間的通訊流程是怎樣的?

    QAT相關(guān)的名詞組織關(guān)系是什么?處理器和PCH設(shè)備之間的通訊流程是怎樣的?服務(wù)實(shí)例與硬件是如何交互的?
    發(fā)表于 07-23 08:12

    StratoVirt 的 virtio-blk 設(shè)備是如何實(shí)現(xiàn)的?

    virtio-blk 設(shè)備支持一個(gè)隊(duì)列:request_queue。該隊(duì)列負(fù)責(zé) block 設(shè)備初始化以及 IO 命令傳輸。StratoVirt 為該隊(duì)列配置了對(duì)應(yīng)的 event_
    發(fā)表于 06-29 10:37

    LINUX系統(tǒng)引導(dǎo)和初始化-LINUX內(nèi)核解讀

    Linux 的系統(tǒng)引導(dǎo)和初始化 ----------Linux2.4.22內(nèi)核解讀之一 一、 系統(tǒng)引導(dǎo)和初始化概述 相關(guān)代碼(引導(dǎo)扇區(qū)的程序及其輔助程序,以 x86體系為例): \
    發(fā)表于 11-03 22:31 ?53次下載

    objc源碼NSObject如何進(jìn)行初始化

    + alloc 和 - init 這一對(duì)我們?cè)?iOS 開(kāi)發(fā)每天都要用到的初始化方法一直困擾著我, 于是筆者仔細(xì)研究了一下 objc 源碼 NSObject 如何進(jìn)行初始化。 在具
    發(fā)表于 09-26 09:58 ?0次下載

    Linux內(nèi)存初始化

    之前有幾篇博客詳細(xì)介紹了Xen的內(nèi)存初始化,確實(shí)感覺(jué)這部分內(nèi)容蠻復(fù)雜的。這兩天在看Linux內(nèi)核啟動(dòng)內(nèi)存的初始化,也是看的云里霧里的,想嘗試下邊看邊寫(xiě),在寫(xiě)博客的過(guò)程
    發(fā)表于 10-12 11:16 ?0次下載

    Linux內(nèi)核初始化過(guò)程調(diào)用順序

    所有的__init函數(shù)在區(qū)段.initcall.init還保存了一份函數(shù)指針,在初始化時(shí)內(nèi)核會(huì)通過(guò)這些函數(shù)指針調(diào)用這些__init函數(shù)指針,并在整個(gè)初始化完成后,釋放整個(gè)init區(qū)段
    發(fā)表于 05-12 08:40 ?1780次閱讀

    uboot中進(jìn)行LCD初始化流程免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是uboot中進(jìn)行LCD初始化流程免費(fèi)下載。
    發(fā)表于 08-12 08:00 ?11次下載
    uboot中進(jìn)行LCD<b class='flag-5'>初始化</b>的<b class='flag-5'>流程</b>免費(fèi)下載

    UCOS2系統(tǒng)內(nèi)核講述(二)_ 初始化調(diào)用函數(shù)

    UCOS2系統(tǒng)內(nèi)核講述(二)_初始化調(diào)用函數(shù)
    的頭像 發(fā)表于 03-25 09:57 ?2048次閱讀
    UCOS2系統(tǒng)內(nèi)核講述(二)_ <b class='flag-5'>初始化</b><b class='flag-5'>調(diào)用</b>函數(shù)

    eMMC初始化命令發(fā)送流程

    eMMC初始化命令發(fā)送流程通過(guò)stm32單片機(jī)驅(qū)動(dòng)eMMC芯片,在完成項(xiàng)目的過(guò)程,命令發(fā)送和響應(yīng)很令人頭疼,所以整理出一篇文檔供各位開(kāi)發(fā)者參考。初始化命令發(fā)送
    發(fā)表于 12-05 19:21 ?18次下載
    eMMC<b class='flag-5'>初始化</b>命令發(fā)送<b class='flag-5'>流程</b>

    Linux終端初始化和tty驅(qū)動(dòng)框架

    initcall機(jī)制 注意上述流程,我們來(lái)理解一下 initcall 機(jī)制: 普通我們寫(xiě)一個(gè)程序,想要它被調(diào)用,需要在主流程調(diào)用這個(gè)函數(shù),
    的頭像 發(fā)表于 09-28 16:33 ?1064次閱讀
    <b class='flag-5'>Linux</b>終端<b class='flag-5'>初始化</b>和tty驅(qū)動(dòng)框架

    OP-TEE的內(nèi)核初始化函數(shù)調(diào)用

    generic_boot_init_primary函數(shù)內(nèi)容 generic_boot_init_primary函數(shù)是OP-TEE建立系統(tǒng)運(yùn)行環(huán)境的入口函數(shù),該函數(shù)會(huì)進(jìn)行建立線程運(yùn)行空間、初始化
    的頭像 發(fā)表于 11-02 18:18 ?1137次閱讀
    OP-TEE的內(nèi)核<b class='flag-5'>初始化</b>函數(shù)<b class='flag-5'>調(diào)用</b>

    IM系列設(shè)備過(guò)載故障:界面初始化終止的診斷流程與修復(fù)指南

    當(dāng) IM 系列設(shè)備出現(xiàn)過(guò)載故障導(dǎo)致界面初始化終止時(shí),通常表現(xiàn)為設(shè)備啟動(dòng)后操作界面無(wú)顯示、指示燈異常閃爍或初始化進(jìn)度條停滯不前,同時(shí)可能伴隨設(shè)備
    的頭像 發(fā)表于 06-28 09:47 ?388次閱讀