精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

萬千設備,linux內核如何知道?

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

1、簡介

本文基于內核源碼4.19.4分析。

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

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

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

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

(2)調用device_add():該函數用于將device添加到linux內核的device樹中。

2、device_initialize分析

該函數接收一個struct device *dev參數,在該函數中初始化struct device結構中的幾個重要成員:

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

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

初始化dev中的kobject,并指定與這個對象相關聯的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,表示此時還沒有對應驅動attach到這個設備。

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

3、device_add分析

(1)調用get_device(dev)增加device的引用計數。

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

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

(3)設置device的name:

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

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

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

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

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

error=device_create_file(dev,&dev_attr_uevent);

dev_attr_uevent是一個struct device_attribute類型的數據,該結構用于描述導出設備屬性的接口,定義如下:

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目錄下為設備創建符號鏈接,以便用戶空間程序能夠方便地訪問和管理設備。

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

error=device_add_attrs(dev);

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

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

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

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

bus_add_device的執行邏輯:

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

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

(3)調用device_add_groups將bus_dev_groups添加到內核中。

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

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

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

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

(10)創建設備節點:

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

(11)通過bus_notifier告知系統設備已經添加:

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

(12)調用bus_probe_device()為該設備probe一個驅動。該函數實現如下:

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

具體執行流程如下:

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

(2)如果設置了driver_autoprobe,則調用device_initial_probe(dev)。該函數本質調用到device_attach(),嘗試將設備連接到驅動程序。

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

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

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

在內核中,struct class_interface是用于表示設備類和設備驅動之間的接口的結構體。它定義了設備類與設備驅動之間的關聯關系,允許設備驅動在注冊時與相應的設備類進行關聯,并提供了一組函數指針,用于設備類調用設備驅動中的操作。

struct class_interface結構體定義如下:

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: 指向與該接口相關聯的設備類。

add: 指向設備類調用設備驅動的添加操作的函數指針。當設備添加到設備類時,會調用此函數。

remove: 指向設備類調用設備驅動的移除操作的函數指針。當設備從設備類中移除時,會調用此函數。

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

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

4、總結

結合本文內容和linux內核源碼,得出以下結論:

(1)在設備驅動模型中,所有的設備注冊操作最后都會調用device_register()函數實現。

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

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





審核編輯:劉清

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

    關注

    115

    文章

    6154

    瀏覽量

    144231
  • Linux系統
    +關注

    關注

    4

    文章

    591

    瀏覽量

    27353
  • dma
    dma
    +關注

    關注

    3

    文章

    559

    瀏覽量

    100421
  • LINUX內核
    +關注

    關注

    1

    文章

    316

    瀏覽量

    21617
  • numa
    +關注

    關注

    0

    文章

    7

    瀏覽量

    3832

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

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

收藏 人收藏

    評論

    相關推薦

    Linux設備驅動開發詳解:基于最新的Linux 4.0內核

    Linux設備驅動開發詳解:基于最新的Linux 4.0內核
    發表于 08-31 12:29

    什么是linux設備驅動看了就知道

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

    如何編譯設備樹和Linux內核鏡像文件

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

    Linux內核教程

    本章學習目標掌握LINUX內核版本的含義理解并掌握進程的概念掌握管道的概念及實現了解內核的數據結構了解LINUX內核的算法掌握
    發表于 04-10 16:59 ?0次下載

    linux內核kernel-api

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

    Linux設備驅動開發詳解》第4章、Linux內核模塊

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

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

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

    谷歌Android設備內核引入主線Linux內核難嗎?

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

    linux內核是什么_linux內核學習路線

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

    linux內核參數設置_linux內核的功能有哪些

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

    最硬核的Linux內核文章

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

    快速理解什么是Linux內核以及Linux內核的內容

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

    如何才能編譯Linux內核

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

    如何使用Linux內核實現USB驅動程序框架

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

    linux驅動程序如何加載進內核

    Linux系統中,驅動程序是內核與硬件設備之間的橋梁。它們允許內核與硬件設備進行通信,從而實現對硬件
    的頭像 發表于 08-30 15:02 ?376次閱讀