日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux驱动加载 动态加载 静态加载 自动加载

發布時間:2023/12/10 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux驱动加载 动态加载 静态加载 自动加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

在咱們工作中,編譯驅動,加載驅動時最常見的事。但是內核是如何加載驅動的,有些事編譯到內核里面,有些事編譯成ko,有些還能放到root下,讓系統自動加載。

總的說來,在Linux下可以通過兩種方式加載驅動程序:靜態加載和動態加載。

靜態加載就是把驅動程序直接編譯進內核,系統啟動后可以直接調用。動態加載利用了Linux的module特性,可以在系統啟動后用insmod命令添加模塊(.ko),在不需要的時候用rmmod命令卸載模塊。

?

?

驅動加載

靜態加載過程

?

將模塊的程序編譯到Linux內核中,也就是咱們在編譯內核時選擇Y的模塊,靜態由do_initcall函數加載先來看看initcall在哪里:

核心進程(/init/main.c)

start_kernel()//內核啟動的入口,負責初始化調度,中斷,內存,最后啟動1號進程 和2號進程

? ? ?rest_init()

? ? ? ? ? kernel_init()//這是誰? linux 1號進程,top一下系統就能找到1號進程了。

? ? ? ? ? ? ? do_basic_setup()

? ? ? ? ? ? ? ? ? ? do_initcalls()

?

do_initcalls中會定義的各個模塊加載順序,加載順序分為16個等級,加載時按照16個等級依次加載內核驅動。關于每個等級的定義參考/include/linux/init.h舉個例子,在2.6.24的內核 中:gianfar_device使用的是arch_initcall,而gianfar_driver使用的是module_init,因為 arch_initcall的優先級大于module_init,所以gianfar設備驅動的device先于driver在總線上添加。

?

動態加載過程

將模塊的程序編譯成KO也就是咱們在編譯內核時選擇M的模塊,通過insmod

modprobe 或者udev動態加載到內核中?insmod絕對路徑/××.ko,而modprobe ××即可,不用加.ko或.o后綴,也不用加路徑;最重要的一點是:modprobe同時會加載當前模塊所依賴的其它模塊

來看看insmod都做了什么:

Insmod

? ? insmod_main

? ? ? ? bb_init_module

? ? ? ? ? ? init_module

? ? ? ? ? ? ? ? sys_init_module進入系統調用

? ? ? ? ? ? ? ? ? ? ? sys_init_module()系統調用會調用module_init指定的函數進行模塊的初始化,至此ko加載完成。

?

?

驅動匹配

硬件固件設計

以PCI為例,所有PCI硬件上必須設計一系列寄存器,PCI通過這些寄存器獲取硬件信息,稱為PCI配置空間,PCI配置空間格式如下:

?

PCI標準規定每個設備的配置寄存器組最多可以有256字節的連續空間,其中開頭的64字節的用途和格式是標準的,成為配置寄存器組的“頭部”,這樣的頭部又有兩種,“0型”頭部用于一般的PCI設備,“1型”頭部用于PCI橋,無論是“0型”還是“1型”,其開頭的16個字節的用途和格式是共同的。其中Device ID 和 Vendor ID 位于前4個字節。

在系統中運行LSPCI -NN,會得到類似如下輸出:

?Ethernet controller [0200]: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) [8086:100f] (rev 01)

其中的8086是vendor ID,100f是Device ID。所以咱們常用的LSCPI實質上就是去硬件上讀取硬件的寄存器值,并且顯示出來。

軟件驅動設計

每一個硬件設備都有Verdon ID, Device ID, SubVendor ID等信息。所以每一個設備驅動程序,必須說明自己能夠為哪些Verdon ID, DevieceID, SubVendor ID的設備提供服務。以PCI設備為例,它是通過一個pci_device_id的數據結構來實現這個功能的。例如:RTL8139驅動的pci_device_id定義為:

?

Verdon ID可以理解為廠商ID,8086 代表Intel,1249代表三星等,Device?ID可以理解為產品ID,每款產品的ID不同。上面的信息說明,Verdon ID為0x10EC, Device ID為0x8139, 0x8138的PCI設備(SubVendor ID和SubDeviceID為PCI_ANY_ID,表示不限制。),都可以使用這個驅動程序(8139too)。

下面是內核設備與驅動匹配的代碼:

?

自動加載過程

自動加載屬于動態加載,加載的是ko文件,許多同學也沒搞清楚,系統啟動之后ko在什么時候,通過什么程序自動加載上的。

構建自動加載環境

?

編譯內核時,通過make modules_install INSTALL_MOD_PATH=XXX,會將所有選項為M的模塊編譯為KO, 并且發布到xxx/lib/modules/uname-r/下面。在模塊安裝的時候,depmod會根據模塊中的rtl8139_pci_tbl的信息,生成下面的信息,保存到/lib/modules/uname-r/modules.alias文件中,其內容如下:

?

alias pci:v000010ECd00008138sv*sd*bc*sc*i* 8139too alias pci:v000010ECd00008139sv*sd*bc*sc*i* 8139too ......

?

v后面的000010EC說明其Vendor ID為10EC,d后面的00008138說明Device ID為8139,而sv,和sd為SubVendor ID和SubDevice ID,后面的星號表示任意匹配。

另外在/lib/modules/uname-r/modules.dep文件中還保存這模塊之間的依賴關系,其內容如下:

?

8139too.ko:mii.ko

?

modules.dep由depmod工具生成,在使用 modprobe xxx加載驅動時, modprobe需要借助modules.dep文件來分析模塊之間的依賴關系,先加載依賴的ko,再加載真正需要加載的ko。

?

?

PCI掃描自動加載驅動

在內核啟動過程中,總線驅動程序會會總線協議進行總線枚舉(總線驅動程序總是集成在內核之中,不能夠按模塊方式加載,你可以通過make menuconfig進入Busoptions,這里面的各種總線,你只能夠選擇Y或N,而不能選擇M.),并且為每一個設備建立一個設備對象。每一個總線對象有一個kset對象,每一個設備對象嵌入了一個kobject對象,kobject連接在kset對象上,這樣總線和總線之間,總線和設備設備之間就組織成一顆樹狀結構。當總線驅動程序為掃描到的設備建立設備對象時,會初始化kobject對象,并把它連接到設備樹中,同時會調用kobject_uevent()把這個(添加新設備的)事件,以及相關信息(包括設備的VendorID,DeviceID等信息)通過netlink發送到用戶態中。

來看看這個過程:

subsys_initcall?(前面講到過驅動的16級加載機制,subsys_initcall處于16級中的第8級,arch\x86\pci\legacy.c 參照內核4.19)

pci_legacy_init

pcibios_scan_root

pci_scan_root_bus

pci_scan_slot

pci_scan_single_device

pci_device_add

device_add

?

device_add有兩個流程:

  • bus_probe_device?匹配內核中已有驅動
  • kobject_uevent 發消息到udev,讓udev去/lib/modules/下面加載驅動
  • 在用戶態的udevd檢測到這個事件,就可以根據這些信息,打開/lib/modules/uname-r/modules.alias文件,根據

    ?

    alias pci:v000010ECd00008138sv*sd*bc*sc*i* 8139too

    ?

    得知這個新掃描到的設備驅動模塊為8139too。于是modprobe就知道要加載8139too這個模塊了,同時modprobe根據 modules.dep文件發現,8139too依賴于mii.ko,如果mii.ko沒有加載,modprobe就先加載mii.ko,接著再加載 8139too.ko。

    ?

    總結

    以上是生活随笔為你收集整理的linux驱动加载 动态加载 静态加载 自动加载的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。