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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

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

萬千設備,linux內(nèi)核如何知道?

嵌入式小生 ? 來源:嵌入式小生 ? 2023-07-12 08:52 ? 次閱讀

1、簡介

本文基于內(nèi)核源碼4.19.4分析。

linux內(nèi)核設備的注冊由device_register()函數(shù)完成,這個函數(shù)是linux設備驅(qū)動模型的核心函數(shù),實現(xiàn)在/drivers/base/core.c中:

199d7ba0-204a-11ee-962d-dac502259ad0.png

在device_register()函數(shù)中,分為兩個步驟:

(1)調(diào)用device_initialize():該步驟用于初始化一個device。

(2)調(diào)用device_add():該函數(shù)用于將device添加到linux內(nèi)核的device樹中。

2、device_initialize分析

該函數(shù)接收一個struct device *dev參數(shù),在該函數(shù)中初始化struct device結(jié)構(gòu)中的幾個重要成員:

19b23cac-204a-11ee-962d-dac502259ad0.png

設置dev->kobj.kset為device_kset。device_kset是一個struct kset類型的全局變量,用于向sysfs文件系統(tǒng)中導出目錄:/sys/device/* 。

初始化dev中的kobject,并指定與這個對象相關聯(lián)的ktype為device_type。

初始化dma_pools鏈表。

初始化struct device中的各種鎖:

19d1e322-204a-11ee-962d-dac502259ad0.png

初始化device的電源管理

19f41bf4-204a-11ee-962d-dac502259ad0.png

如果在NUMA下,還會初始化設置device的numa_node為-1。

接著初始化device下的links中的鏈表:

1a0a4da2-204a-11ee-962d-dac502259ad0.png

在struct device 中的links表示鏈接到該設備的suppliers和consumers,由struct dev_links_info表示:

1a1af6f2-204a-11ee-962d-dac502259ad0.png

設置device下的links.status值為DL_DEV_NO_DRIVER,表示此時還沒有對應驅(qū)動attach到這個設備。

以上步驟則是device_initialize()初始化設備時完成的操作。

3、device_add分析

(1)調(diào)用get_device(dev)增加device的引用計數(shù)。

(2)如果dev->p為NULL,則調(diào)用device_private_init()設置device的私有數(shù)據(jù):

1a376102-204a-11ee-962d-dac502259ad0.png

(3)設置device的name:

1a53a498-204a-11ee-962d-dac502259ad0.png

如果開啟支持pr_debug()函數(shù),則會打印出對應的設備名稱。

(4)尋找父設備和父設備對應的kobj,并調(diào)用kobject_add()將dev->kobj添加到dev->kobj.parent:

1a6f4130-204a-11ee-962d-dac502259ad0.png

(5)使用device_create_file為device創(chuàng)建sysfs屬性文件:

error=device_create_file(dev,&dev_attr_uevent);

dev_attr_uevent是一個struct device_attribute類型的數(shù)據(jù),該結(jié)構(gòu)用于描述導出設備屬性的接口,定義如下:

structdevice_attribute{
structattributeattr;
ssize_t(*show)(structdevice*dev,structdevice_attribute*attr,
char*buf);
ssize_t(*store)(structdevice*dev,structdevice_attribute*attr,
constchar*buf,size_tcount);
};

(6)添加類的符號鏈接:

error=device_add_class_symlinks(dev);

device_add_class_symlinks()的功能是將設備添加到指定的設備類中,并在/sys/class目錄下為設備創(chuàng)建符號鏈接,以便用戶空間程序能夠方便地訪問和管理設備。

(7)調(diào)用device_add_attrs()為設備添加屬性:

error=device_add_attrs(dev);

device_add_attrs()的功能是為設備添加屬性,并在/sys/devices目錄下創(chuàng)建相應的屬性文件。這樣,用戶空間程序可以通過訪問設備的屬性文件來讀取和修改設備的屬性值。這個函數(shù)在設備驅(qū)動的初始化過程中常常被調(diào)用,以確保設備的屬性能夠正確地顯示和訪問。

(8)調(diào)用bus_add_device()添加設備到bus:

1a8d5b0c-204a-11ee-962d-dac502259ad0.png

bus_add_device用于將設備添加到總線上。它的功能是將一個設備(struct device結(jié)構(gòu)體)添加到指定總線(struct bus_type結(jié)構(gòu)體)上,并進行相應的初始化和注冊操作。

bus_add_device的執(zhí)行邏輯:

(1)從dev->bus中取得bus_type*類型的指針bus,如果獲取bus不成功,則函數(shù)直接返回;如果bus獲取成功,則會繼續(xù)后續(xù)的第(2)步操作。

(2)調(diào)用device_add_attrs接口,將由bus->dev_attrs指針定義的默認attribute添加到內(nèi)核中,這個操作會體現(xiàn)在sysfs文件系統(tǒng)中的/sys/devices/xxx/xxx_device/目錄中。

(3)調(diào)用device_add_groups將bus_dev_groups添加到內(nèi)核中。

(4)調(diào)用sysfs_create_link將該設備在sysfs中的目錄,鏈接到該bus的devices目錄下

(5)接著依然調(diào)用sysfs_create_link,在該設備的sysfs目錄中,創(chuàng)建一個指向該設備所在bus目錄的鏈接,命名為subsystem。

(6)前面幾個操作實則是向sysfs文件系統(tǒng)注冊關于設備的信息,向用戶空間拋出接口。最后步驟則是調(diào)用klist_add_tail()將該設備指針保存到bus->p->klist_devices中。

(9)調(diào)用device_pm_add()將一個設備添加到PM核心的active設備鏈表中。

(10)創(chuàng)建設備節(jié)點:

1aa8bb0e-204a-11ee-962d-dac502259ad0.png

(11)通過bus_notifier告知系統(tǒng)設備已經(jīng)添加:

1ac739f8-204a-11ee-962d-dac502259ad0.png

(12)調(diào)用bus_probe_device()為該設備probe一個驅(qū)動。該函數(shù)實現(xiàn)如下:

1ae151bc-204a-11ee-962d-dac502259ad0.png

具體執(zhí)行流程如下:

(1)從dev中解析出該dev所在而bus,如果bus不存在,則退出該函數(shù)。

(2)如果設置了driver_autoprobe,則調(diào)用device_initial_probe(dev)。該函數(shù)本質(zhì)調(diào)用到device_attach(),嘗試將設備連接到驅(qū)動程序。

(3)遍歷bus上的子系統(tǒng)接口鏈表interfaces,如果add_dev函數(shù)指針存在,則調(diào)用對應的函數(shù)。(從源碼來看有些驅(qū)動程序,會使用struct subsys_interface來實現(xiàn),在此處實現(xiàn)對注冊的subsys_interface下的add_dev的調(diào)用執(zhí)行)

(13)如果父設備存在,則會將該設備添加到父設備的klist_children鏈表中(klist_children是包含此設備的所有子節(jié)點的鏈表):

1afa2ff2-204a-11ee-962d-dac502259ad0.png

(14)如果設備的class不為NULL,則會將class綁定到device:

klist_add_tail(&dev->p->knode_class,&dev->class->p->klist_devices);

(15)通知所有的interface接口:

1b0936aa-204a-11ee-962d-dac502259ad0.png

在內(nèi)核中,struct class_interface是用于表示設備類和設備驅(qū)動之間的接口的結(jié)構(gòu)體。它定義了設備類與設備驅(qū)動之間的關聯(lián)關系,允許設備驅(qū)動在注冊時與相應的設備類進行關聯(lián),并提供了一組函數(shù)指針,用于設備類調(diào)用設備驅(qū)動中的操作。

struct class_interface結(jié)構(gòu)體定義如下:

structclass_interface{
structlist_headnode;
structclass*class;
int(*add)(structdevice*dev,structclass_interface*class_intf);
void(*remove)(structdevice*dev,structclass_interface*class_intf);
};

node: 用于將struct class_interface鏈接到設備類的接口鏈表中。

class: 指向與該接口相關聯(lián)的設備類。

add: 指向設備類調(diào)用設備驅(qū)動的添加操作的函數(shù)指針。當設備添加到設備類時,會調(diào)用此函數(shù)。

remove: 指向設備類調(diào)用設備驅(qū)動的移除操作的函數(shù)指針。當設備從設備類中移除時,會調(diào)用此函數(shù)。

通過使用struct class_interface,設備驅(qū)動可以與設備類進行交互,以便在設備添加或移除時執(zhí)行相應的操作。這種機制允許設備驅(qū)動與設備類解耦,使得設備驅(qū)動可以在設備類的上下文中執(zhí)行一些操作,而無需直接操作設備類。

回到device_add()中,使用了list_for_each_entry()遍歷interfaces鏈表,如果設置了class_intf->add_dev,則調(diào)用該回調(diào)函數(shù)指針指向的函數(shù)。

4、總結(jié)

結(jié)合本文內(nèi)容和linux內(nèi)核源碼,得出以下結(jié)論:

(1)在設備驅(qū)動模型中,所有的設備注冊操作最后都會調(diào)用device_register()函數(shù)實現(xiàn)。

(2)在筆者分析的linux版本下的device_register()中,存在兩個數(shù)據(jù)結(jié)構(gòu):struct class_interface 和struct subsys_interface。從內(nèi)核源碼來看,這兩個結(jié)構(gòu)只在為數(shù)不多的幾個特定驅(qū)動程序中使用,那么可證明這可能是歷史發(fā)展遺留下來的代碼,在device_register中仍然保留了對這部分代碼的支持。

(3)在device_register()中調(diào)用了bus_probe_device(),從而證明在注冊設備的時候發(fā)生了『設備與驅(qū)動匹配』的過程。





審核編輯:劉清

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

    關注

    115

    文章

    6187

    瀏覽量

    144676
  • Linux系統(tǒng)

    關注

    4

    文章

    595

    瀏覽量

    27449
  • dma
    dma
    +關注

    關注

    3

    文章

    566

    瀏覽量

    100741
  • LINUX內(nèi)核

    關注

    1

    文章

    316

    瀏覽量

    21688
  • numa
    +關注

    關注

    0

    文章

    7

    瀏覽量

    3845

原文標題:一臉懵,萬千設備,linux內(nèi)核如何知道?

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux設備驅(qū)動開發(fā)詳解:基于最新的Linux 4.0內(nèi)核

    Linux設備驅(qū)動開發(fā)詳解:基于最新的Linux 4.0內(nèi)核
    發(fā)表于 08-31 12:29

    什么是linux設備驅(qū)動看了就知道

    想要深入理解linux設備驅(qū)動,你必須明確以下幾個問題:· 應用程序、庫、內(nèi)核、驅(qū)動程序的關系· 設備類型· 設備文件、主
    發(fā)表于 04-06 06:50

    如何編譯設備樹和Linux內(nèi)核鏡像文件

    實驗任務:編譯設備樹和Linux內(nèi)核鏡像文件,拷貝到sd卡中,再從sd卡中拷貝到nand閃存對應的分區(qū)中,最后nand啟動,進入linux系統(tǒng)本篇博客內(nèi)容:1.實驗流程2.注意事項1.
    發(fā)表于 12-20 07:11

    Linux內(nèi)核教程

    本章學習目標掌握LINUX內(nèi)核版本的含義理解并掌握進程的概念掌握管道的概念及實現(xiàn)了解內(nèi)核的數(shù)據(jù)結(jié)構(gòu)了解LINUX內(nèi)核的算法掌握
    發(fā)表于 04-10 16:59 ?0次下載

    linux內(nèi)核kernel-api

    linux內(nèi)核kernel-api,不知道從哪兒找的了,但是你如果想要做內(nèi)核編程,這是一部api函數(shù)詳盡的工具書?。?!五星推薦
    發(fā)表于 10-30 17:16 ?19次下載

    Linux設備驅(qū)動開發(fā)詳解》第4章、Linux內(nèi)核模塊

    Linux設備驅(qū)動開發(fā)詳解》第4章、Linux內(nèi)核模塊
    發(fā)表于 10-27 14:15 ?0次下載
    《<b class='flag-5'>Linux</b><b class='flag-5'>設備</b>驅(qū)動開發(fā)詳解》第4章、<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>模塊

    知道linux常用查看硬件設備信息命令的方法是什么?

    知道linux常用查看硬件設備信息命令的方法是什么?
    發(fā)表于 05-13 11:04 ?3168次閱讀

    谷歌Android設備內(nèi)核引入主線Linux內(nèi)核難嗎?

    Android是基于Linux內(nèi)核的操作系統(tǒng),但是,運行在Android設備上的內(nèi)核其實與Google選擇的LTS版本Linux
    的頭像 發(fā)表于 11-22 10:41 ?3075次閱讀
    谷歌Android<b class='flag-5'>設備</b><b class='flag-5'>內(nèi)核</b>引入主線<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>難嗎?

    linux內(nèi)核是什么_linux內(nèi)核學習路線

    Linux內(nèi)核是一個操作系統(tǒng)(OS)內(nèi)核,本質(zhì)上定義為類Unix。它用于不同的操作系統(tǒng),主要是以不同的Linux發(fā)行版的形式。Linux
    發(fā)表于 09-16 15:49 ?2662次閱讀

    linux內(nèi)核參數(shù)設置_linux內(nèi)核的功能有哪些

    本文主要闡述了linux內(nèi)核參數(shù)設置及linux內(nèi)核的功能。
    發(fā)表于 09-17 14:40 ?1388次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>參數(shù)設置_<b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>的功能有哪些

    最硬核的Linux內(nèi)核文章

    來源 :頭條號@Linux學習教程,冰凌塊兒 01 前言 本文主要講解什么是Linux內(nèi)核,以及通過多張圖片展示Linux內(nèi)核的作用與功能,
    的頭像 發(fā)表于 10-19 17:46 ?2141次閱讀
    最硬核的<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>文章

    快速理解什么是Linux內(nèi)核以及Linux內(nèi)核的內(nèi)容

    01 前言 本文主要講解什么是Linux內(nèi)核,以及通過多張圖片展示Linux內(nèi)核的作用與功能,以便于讀者能快速理解什么是Linux
    的頭像 發(fā)表于 10-21 12:02 ?4316次閱讀
    快速理解什么是<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>以及<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的內(nèi)容

    如何才能編譯Linux內(nèi)核

    內(nèi)核,是一個操作系統(tǒng)的核心。它負責管理系統(tǒng)的進程、內(nèi)存、設備驅(qū)動程序、文件和網(wǎng)絡系統(tǒng),決定著系統(tǒng)的性能和穩(wěn)定性。Linux 作為一個自由軟件,在廣大愛好者的支持下,內(nèi)核版本不斷更新。新
    發(fā)表于 11-04 18:04 ?8次下載

    如何使用Linux內(nèi)核實現(xiàn)USB驅(qū)動程序框架

    Linux內(nèi)核提供了完整的USB驅(qū)動程序框架。USB總線采用樹形結(jié)構(gòu),在一條總線上只能有唯一的主機設備Linux內(nèi)核從主機和
    發(fā)表于 11-06 17:59 ?20次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>實現(xiàn)USB驅(qū)動程序框架

    linux驅(qū)動程序如何加載進內(nèi)核

    Linux系統(tǒng)中,驅(qū)動程序是內(nèi)核與硬件設備之間的橋梁。它們允許內(nèi)核與硬件設備進行通信,從而實現(xiàn)對硬件
    的頭像 發(fā)表于 08-30 15:02 ?530次閱讀