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

歡迎訪問 生活随笔!

生活随笔

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

linux

[driver]linux内核动态加载模块

發布時間:2024/4/17 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [driver]linux内核动态加载模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
問題: 1. 把編譯好的模塊放到板子/lib/modules對應文件夾下,并且執行了depmod -a, 比如pl2303.ko, 那么下一次插入pl2303的串口線,是否可以識別,也就是自動加載pl2303驅動? -------------------------------------------------------------------------------------------------------------- 轉自:http://blog.csdn.net/hunanchenxingyu/article/details/47292327

一、安裝內核模塊

一般步驟:

  • 在/usr/src/Linux/下運行make menuconfig把需要編譯成模塊的項打上(M),保存并退出。
  • 運行make modules,這一步將在/usr/src/linux/下生成*.o或*.ko文件。
  • 運行make modeules_install來安裝,這步會把生成的.o或ko文件拷貝到/lib/modules/`uname -r`/下。
  • 如果你只要編譯某一個或幾個模塊,就可以用下面這個快速的方法:

  • 找到編譯內核所需要的.config文件。?在/usr/src/linux/arch目錄下有若干編譯內核所用的配置。選擇我們想要的配置,將它復制到/usr/src/linux目錄下,改名為.config。?cp /usr/src/linux/arch/x86/xxconfig /usr/src/linux/.config
  • 修改.config文件,去掉不用的模塊,加上自己想要的模塊。?打開.config,有許多XXXX=m的項,這些都是要被編譯為模塊 的項,因為我們不希望編譯這些模塊,所以要把XXXX=m的項統統去掉。然后再加上我們想要的模塊,例如將# CONFIG_NTFS_FS is not set 改為CONFIG_NTFS_FS=m 當然,可以用你熟悉各種工具來做這件事。
  • 編譯NTFS模塊。在/usr/src/linux目錄下運行命令make modules來編譯我們想要的模塊。
  • 安裝模塊。?編譯后得到的.o文件在/usr/src/linux/目錄下,手動將它復制到正確的目錄下。?例如cp /usr/src/linux/fs/ntfs/ntfs.o /lib/modules/2.2.16-22/fs/
  • ?注意:千萬不能運行命令make modules_install,否則將帶來嚴重的后果,它會刪除你系統中的所有模塊,只安裝剛剛編譯的模塊(ntfs.o)。

    二:安裝完成以后,我們就可以加載模塊了

    和linux中加載模塊有關的幾個命令分別如下:

    depmod,?modprobe,?lsmod

    2.1.先來看看depmod命令:

    depmod是一個 用來產生modules.dep和map文件的程序。在modules.dep文件中空白行和以'#'開頭的行將被忽略.depmod通過讀取/lib /modules/version目錄下的每一個模塊來創建一個記錄模塊相依性的列表。這個列表就是/lib/modules/version目錄下的 modules.dep。depmod也會在/lib/modules/version目錄下創建許多map文件,例如 modules.dep,modules.isapnpmap,modules.pcimap,modules.alias這些文件將會被hotplug 用到。

    OPTIONS:
    -a --all Probe all modules. This option is enabled by default if no
    ??????????? file names are given in the command-line.
    檢查所有的模塊,這個命令是默認的如果你沒有指定模塊名字的話。

    -A --quick This option scans to see if any modules are newer than the
    ???????????????? modules.dep file before any work is done%3

    2.2.再來看看modprobe命令:

    modprobe 命令是根據depmod -a的輸出/lib/modules/version/modules.dep來加載全部的所需要模塊。可以通過modprobe -l來顯示可以當前可以加載的模塊。modprobe 在掛載模塊是不用指定模塊文件的路徑,也不用帶文件的后綴.o 或.ko,?而insmod 需要的是模塊的所在目錄的絕對路徑,并且一定要帶有模塊文件名后綴的(modulefile.o 或modulesfile.ko )。?insmod比較重要的用途是用來測試模塊的正確性,加載一般都是依靠modprobe。

    用法:modprobe xxx.ko??????? #加載某個模塊
    modprobe -r xxx.ko???? #卸載某個模塊

    2.3.lsmod:

    lsmod?顯示當前加載的所有 模塊,相當于cat /proc/modules,假設你沒有設定開機加載某個模塊,比如ntfs,那么開機后執行lsmod,列表里不會有ntfs這個模塊的,這時你再執行 mount -t ntfs xxx后,執行lsmod后列表里就會有ntfs這個模塊了。
    還要注意的是lsmod顯示的是模塊名,而不是別名(alias)。

    2.4.modinfo

    顯示kernel模塊的對象文件,以顯示該模塊的相關信息

    三、系統如何完成動態加載

    在內核中有一個“Automatic kernel module loading"功能被編譯到了內核中。當用戶嘗試打開某類型的文件時,內核會根據需要嘗試加載相應的模塊。我們來看看驅動程序自動加載是怎么實現的:

    ? 每一個設備都有Verdon ID, Device ID, SubVendor ID等信息。而每一個設備驅動程序,必須說明自己能夠為哪些Verdon ID, Deviece

    ? ID, SubVendor ID的設備提供服務。以PCI設備為例,它是通過一個pci_device_id的數據結構來實現這個功能的。例如:RTL8139的pci_device_id定義為:

    static struct pci_device_id rtl8139_pci_tbl[] = {{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },...... }

    在模塊安裝的時候,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 ......

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

    (這里省去了路徑信息。)

    8139too.ko:mii.ko

    在內核啟動過程中,

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

    實驗

    在你的shell中,運行:

    # ps aux | grep udevd

    # kill -9 25063 然后跟蹤udevd,在shell中運行:

    ?# strace -f /sbin/udevd --daemon??這時,我們看到udevd的輸出如下:

    ......close(8) = 0munmap(0xb7f8c000, 4096) = 0select(7, [3 4 5 6], NULL, NULL, NULL

    我們發現udevd在這里被阻塞在select()函數中。 select函數原型如下: ?int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);??

    • 第一個參數:nfds表示最大的文件描述符號,這里為7(明明是6 ?)。
    • 第二個參數:readfds為讀文件描述符集合,這里為3,4,5,6.
    • 第三個參數:writefds為寫文件描述符集合,這里為NULL。
    • 第四個參數:exceptfds為異常文件描述符集合,這里為NULL。 第五個參數:timeout指定超時時間,這里為NULL。

    select函數的作用是:

    如果readfds中的任何一個文件有數據可讀,或者witefds中的任何一個文件可以寫入,或者exceptfds中的任 何一個文件出現異常時,就返回。否則阻塞當前進程,直到上訴條件滿足,或者因阻塞時間超過了timeout指定的時間,當前進程被喚醒,select返 回。 所以,在這里udevd等待3,4,5,6這幾個文件有數據可讀,才會被喚醒。現在,到shell中運行:? # ps aux | grep udevd root 27615 ...... strace -o /tmp/udevd.debug -f /sbin/udevd --daemon root 27617 ...... /sbin/udevd --daemon? udevd的進程id為27617,現在我們來看看select等待的幾個文件: # cd /proc/27615/fd # ls -l udevd的標準輸入,標準輸出,標準錯誤全部為?/dev/null. 0 -> /dev/null 1 -> /dev/null 2 -> /dev/null? udevd在下面這幾個文件上等待。? 3 -> /inotify 4 -> socket:[331468] 5 -> socket:[331469] 6 -> pipe:[331470] 7 -> pipe:[331470]?

    由于不方便在運行中插入一塊8139的網卡,因此現在我們以一個U盤來做試驗,當你插入一個U盤后,你將會看到strace的輸出,從它的輸出可以看到 udevd在select返回后,調用了modprobe加載驅動模塊,并調用了sys_mknod,在dev目錄下建立了相應的節點。?

    execve("/sbin/modprobe", ["/sbin/modprobe", "-Q", "usb:v05ACp1301d0100dc00dsc00dp00"...] ...... mknod("/dev/sdb", S_IFBLK|0660, makedev(8, 16)) = 0 ......

    這里modprobe的參數"usb:v05AC..."對應modules.alias中的某個模塊。 可以通過udevmonitor來查看內核通過netlink發送給udevd的消息,在shell中運行: # udevmonitor --env 然后再插入U盤,就會看到相關的發送給udevd的消息。

    四、內核模塊加載的配置:

    有時候需要一次性加載許多模塊,需要在一個地方統一配置modprobe的選項等,有一個比較重要的文件:?/etc/modprobe.conf?, 在opensuse中,和它有關的還有modprobe.d/文件夾下的許多文件和?modprobe.conf.local?文件,在? /etc/modprobe.conf?里會include其它所有的文件,一般建議在?modprobe.conf.local?中修改自己的配置。??/etc/modprobe.conf?其實就是用于?寫入模塊的加載命令或模塊的別名的定義等。?man modprobe.conf?:

    alias?my-mod really_long_modulename為模塊定義一個便于使用的別名

    options?modulename option...在加載模塊時添加選項

    install?modulename command...使用自己定義的命令去加載指定的模塊,如install fred /sbin/modprobe barney; /sbin/modprobe
    ????????????? --ignore-install fred" 每次加載fred模塊的時候用的是?“/sbin/modprobe barney; /sbin/modprobe
    ????????????? --ignore-install fred”命令

    remove?modulename command...用自己定義的命令刪除指定的模塊。

    include?filename 引入其它文件

    blacklist?modulename 不再加載某個模塊

    五、內核模塊開機自動掛載:

    對于開機自動掛載模塊,在redhat系統里,網上說在內核啟動的過程中,init執行/etc/rc.d/rc.sysinit后,啟動內核外掛模塊?時會讀取?/etc/modprobe.conf?這個文件。在2.4的內核中,?只 要直接修改/etc/modprobe.conf加入install xxx即可。2.6內核則需修改/etc/rc.d/rc.sysinit文件。具體的過程可以看:http://blog.csdn.NET/ioriqqe/archive/2009/11/05/4772033.aspx

    而在suse里,可以在root權限編輯/etc/sysconfig/kernel文件,添加需要啟動的模塊。

    ?

    轉載于:https://www.cnblogs.com/aaronLinux/p/6970590.html

    總結

    以上是生活随笔為你收集整理的[driver]linux内核动态加载模块的全部內容,希望文章能夠幫你解決所遇到的問題。

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