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

歡迎訪問 生活随笔!

生活随笔

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

linux

(四)Linux内核模块化编程

發布時間:2025/3/8 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (四)Linux内核模块化编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

        • (一)模塊化編程簡介
        • (二)安裝卸載模塊命令.
        • (三)將自定義功能添加到內核三種方法
            • (1)修改Kconfig和Makefile
            • (2)直接修改功能對應目錄下的Makefile文件
            • (3)在內核目錄中,將功能編譯成模塊文件,后期加載到內核中
        • (四)模塊文件模板
        • (五)單模塊編程
        • (六)多模塊編程
            • (1)多個模塊編譯成多個.ko文件
            • (2)多個模塊編譯成一個.ko文件
        • (七)向模塊傳參

(一)模塊化編程簡介

Linux 內核整體結構已經很龐大,包含了很多的組件,而對于我們工程師而言,有兩種方法,將需要的功能包含進內核當中。

一:將所有的功能都編譯進 Linux 內核。 二:將需要的功能編譯成模塊,在需要的時候動態地添加。

我們在開發測試時常選擇第二種方式,原因是程序反復修改,不適合直接編譯到內核。 模塊起到約束作用,意味著內核中所有的模塊化程序均要遵循統一規則,否則無法添加到內核。

(二)安裝卸載模塊命令.

命令解釋
insmod將模塊添加進內核
rmmod將模塊從內核卸載
lsmod查看已安裝到內核的模塊
modprobe載入指定的個別模塊,或是載入一組相依賴的模塊。 modprobe 會根據 depmod 所產生的依賴關系,決定要載入哪些模塊。若在載入 過程中發生錯誤,在 modprobe 會卸載整組的模塊。依賴關系是通過讀取 /lib/modules/2.6.xx/modules.dep 得到的。而該文件是通過depmod 所建立。
modinfo查看模塊信息。使用方法:modinfo XXX.ko
tree –a查看當前目錄的整個樹結構

(三)將自定義功能添加到內核三種方法

(1)修改Kconfig和Makefile

通過修改內核的配置文件
Kconfig:在Kconfig文件中將自定義功能添加到選項菜單中,用來進行是否將功能添加到內核的選項功能的配置,Y標識編譯到內核M標識編譯為模塊文件N標識不對功能做任何操作

config TINY4412_HELLO_MODULE //配置選項名tristate "Tiny4412 module sample" //在菜單中顯示的名稱//tristate :三態,Y,M,N,此位置或者為bool雙態,Y,Ndepends on ARCH_EXYNOS4 //依賴的處理架構help //提示相關的信息Tiny4412 module sample.

我們在linux-3.5/drivers/char的Kconfig中加入上面的代碼:

執行:

make menuconfig //需要在頂級目錄執行 //若無法打開需要安裝庫 apt install ncurses-dev

在界面里多出了一項:

這里僅僅是添加了編譯選項,還需要在對應的Makefile文件進行修改
兩個文件必須同時修改才能達到將功能添加到內核的操作
進入到linux-3.5/drivers/char執行

vim Makefile


經過上面的kcofig和Makefile修改,我們在頂級目錄下執行make -j8 就可以編譯內核,然后下載到開發板查看現象了

(2)直接修改功能對應目錄下的Makefile文件

具體的修改和前面方法類似,不做過多介紹

obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-$(CONFIG_TTY_PRINTK):選項名稱 obj-y:y標識yes 直接選中編譯到內核,無需在Kconfig中進行功能選項配置 obj-m:直接編譯成模塊文件,Linux中模塊文件編譯后以.ko結尾
(3)在內核目錄中,將功能編譯成模塊文件,后期加載到內核中

將模塊加載到內核的方法

insmod xxx.ko

查看模塊使用情況:

lsmod xxx.ko

將模塊從內核卸載:

rmmod xxx.ko

可以在任意目錄下對模塊文件進行編譯,而不局限內核目錄
關于模塊文件的編寫,我們在下面進行詳細的講解。

(四)模塊文件模板

1.模塊文件模板(module.c)

static int __init XXX_init(void)//模塊加載函數 { //這里面做一些初始化工作 return 0; } static void __exit XXX_exit(void)//模塊卸載函數 { //這里面做一些模塊卸載相關的工作 } moudle_init(XXX_init); // 當執行#insmod 時調用,可以看作模塊的入口 moudle_exit(XXX_exit); // 執行#rmmod 時調用,完成模塊注銷操作//必須有 MODULE_LICENSE("GPL");//模塊的開源許可協議 // 模塊的聲明(非必須) MODULE_AUTHOR // 聲明作者 MODULE_DESCRIPTION // 對模塊簡單的描述 MODULE_VERSION // 聲明模塊的版本 MODULE_ALIAS // 模塊的別名 MODULE_DEVICE_TABLE // 告訴用戶空間這個模塊所支持的設備

模塊的卸載函數和模塊加載函數實現相反的功能,主要包括:
1) 若模塊加載函數注冊了 XXX,則模塊卸載函數注銷 XXX
2) 若模塊加載函數動態分配了內存,則模塊卸載函數釋放這些內存
3) 若模塊加載函數申請了硬件資源,則模塊卸載函數釋放這些硬件資源
4) 若模塊加載函數開啟了硬件資源,則模塊卸載函數一定要關閉這些資源

2.Makefile模板文件

CFLAG=-C TARGET=cdev #你自己的模塊文件名 KERNEL=/driver/linux-3.5 #linux內核頂級目錄路徑 obj-m +=$(TARGET).o all:make $(CFLAG) $(KERNEL) M=$(PWD) clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean

(五)單模塊編程

單模塊即一個模塊編譯成一個.ko文件
例子:
tiny_hello_module.c

#include <linux/kernel.h> #include <linux/module.h> //加載函數入口 static int __init Test_module_init(void) {printk("歡迎撬開內核驅動編程的大門\n");return 0; } //卸載函數入口 static void __exit Test_module_cleanup(void) {printk("很機智,知難而退\n"); } module_init(Test_module_init); module_exit(Test_module_cleanup); MODULE_LICENSE("GPL");//如果不準尋GPL協議會報污染內核 /* MODULE_AUTHOR // 聲明作者 MODULE_DESCRIPTION // 對模塊簡單的描述 MODULE_VERSION // 聲明模塊的版本 MODULE_ALIAS // 模塊的別名 MODULE_DEVICE_TABLE // 告訴用戶空間這個模塊所支持的設備 */

Makefile

CFLAG=-C TARGET=tiny_hello_module KERNEL=/driver/linux-3.5 obj-m += $(TARGET).o all:make $(CFLAG) $(KERNEL) M=$(PWD) clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean

執行make后,會生成.ko模塊文件

make

(六)多模塊編程

多模塊即多個模塊.c編譯成多個.ko文件,一般這種情況下存在模塊之間的功能調用,如模塊1調用了模塊2中的功能函數。
內核模塊之間要進行功能調用,需要借助接口EXPORT_SYMBOL(被調用函數名) 對被調用函數進行聲明。
多模塊加載順序:

先加載被調用功能所在的模塊到內核,再加載調用功能的模塊到內核,卸載的順序相反
(1)多個模塊編譯成多個.ko文件
模塊1: #include <linux/kernel.h> #include <linux/module.h> void print() {printk("this is a module test\n"); } EXPORT_SYMBOL(print); //加載函數入口 static int __init Test_module_init(void) {printk("歡迎撬開驅動大門\n");print();return 0; } //卸載函數入口 static void __exit Test_module_cleanup(void) {printk("知難而退,聰明\n"); } module_init(Test_module_init); module_exit(Test_module_cleanup); MODULE_LICENSE("GPL");//如果不準尋GPL協議會報污染內核

模塊2:

#include <linux/kernel.h> #include <linux/module.h> extern void print(); //加載函數入口 static int __init Test_module_init(void) {print();printk("歡迎撬開內核驅動編程的大門\n");return 0; } //卸載函數入口 static void __exit Test_module_cleanup(void) {printk("很機智,知難而退\n"); } module_init(Test_module_init); module_exit(Test_module_cleanup); MODULE_LICENSE("GPL");//如果不遵循GPL協議會報污染內核

Makefile

CFLAG=-C TARGET=tiny_hello_module TARGET1=test_hello_module KERNEL=/driver/linux-3.5 obj-m += $(TARGET).o $(TARGET1).o all:make $(CFLAG) $(KERNEL) M=$(PWD) clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean
(2)多個模塊編譯成一個.ko文件

被加載功能:

#include <linux/kernel.h> #include <linux/module.h> void print() { printk("this is a module test\n"); } EXPORT_SYMBOL(print);

加載功能的模塊

#include <linux/kernel.h> #include <linux/module.h> extern void print(); //加載函數入口 static int __init Test_module_init(void) {print();printk("歡迎撬開內核驅動編程的大門\n");return 0; } //卸載函數入口 static void __exit Test_module_cleanup(void) {printk("很機智,知難而退\n"); } module_init(Test_module_init); module_exit(Test_module_cleanup); MODULE_LICENSE("GPL");//如果不準尋GPL協議會報污染內核

Makefile

CFLAG=-C TARGET=tiny_hello_module TARGET1=test_hello_module KERNEL=/driver/linux-3.5 obj-m += test.o test-objs += $(TARGET).o $(TARGET1).o all:make $(CFLAG) $(KERNEL) M=$(PWD) clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean

(七)向模塊傳參

普通變量:

module_param(變量名, 變量的類型, 權限) 語法:module_param(變量名,變量類型,變量的訪問權限) 變量的訪問權限:變量在文件系統以一個文件形式呈現,這個文件權限屬性就是“變量的訪問權限”。 變量傳遞參數:insmod xx.ko 變量名=值

type支持的基本類型有:
bool :布爾類型
invbool:顛倒了值的bool類型;
charp :字符指針類型,內存為用戶提供的字符串分配;(char )
int :整型
long :長整型
short :短整型
uint :無符號整型(unsigned int)
ulong :無符號長整型(unsigned long)
ushort :無符號短整型(unsignedshort)
指針類只能char,對應名字 charp .
example:

#include <linux/kernel.h> #include <linux/module.h> int num=0; module_param(num,int,0); //加載函數入口 static int __init Test_module_init(void) { int i=0; for(i=0;i<num;i++)printk("歡迎撬開內核驅動編程的大門\n");return 0; } //卸載函數入口 static void __exit Test_module_cleanup(void) {printk("很機智,知難而退\n"); } module_init(Test_module_init); module_exit(Test_module_cleanup); MODULE_LICENSE("GPL");//如果不準尋GPL協議會報污染內核

Makefile

CFLAG=-C TARGET=tiny_hello_module KERNEL=/driver/linux-3.5 obj-m +=$(TARGET).o all:make $(CFLAG) $(KERNEL) M=$(PWD) clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean [root@ubuntu:/home]#insmod tiny_hello_module.ko num=5

數組變量:

對于數組類型變量使用module_param_array。 語法:module_param_array(數組名,數組元素類型,&用來保存傳遞數組袁術個數的變量,變量的訪問權限)num 是一個 char ,int,long 或uchar,uint,ulong類型的變量,用于保存傳遞給數組的元素個數。 數組傳遞參數: insmod xx.ko 數組名=元素0,元素1,元素2, ……

總結

以上是生活随笔為你收集整理的(四)Linux内核模块化编程的全部內容,希望文章能夠幫你解決所遇到的問題。

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