(四)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,  ……

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531422.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531422.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531422.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于X86平臺的PC機通過網絡發送一個int(32位)整數的字節順序

1.字節順序  字節順序是指占內存多于一個字節類型的數據在內存中的存放順序&#xff0c;通常有小端、大端兩種字節順序。小端字節序指低字節數據存放在內存低地址處&#xff0c;高字節數據存放在內存高地址處&#xff1b;大端字節序是高字節數據存放在低地址處&#xff0c;低字…

Linux內核空間和用戶空間

在Linux系統中存在進程的概念&#xff1a; 進程的分類&#xff1a; 用戶進程&#xff1a;運行在用戶空間的進程被稱為用戶進程 內核進程:運行在內核空間的進程被稱為內核進程 進程的空間&#xff1a; 系統會為每一個進程分0-4G的虛擬尋址空間&#xff0c;在4G的空間中 0-3G&…

codeforces Round #320 (Div. 2) C. A Problem about Polyline(數學) D. Or Game(暴力,數學)

解題思路&#xff1a;就是求數 n 對應的二進制數中有多少個 1 #include <iostream> #include<cstdio> using namespace std; int main(){int n;cin>>n;int ans 0; // while(n){//這也是一種好的方法 // n n&(n-1); // ans; // }while(n…

(五)Linux之設備驅動模型

目錄&#xff08;一&#xff09;Linux內核驅動簡介&#xff08;二&#xff09;雜項設備驅動模型&#xff08;1&#xff09;相關接口&#xff08;2&#xff09;雜項設備注冊過程&#xff08;三&#xff09;早期經典字符設備驅動模型&#xff08;1&#xff09;相關接口&#xff0…

操作系統頁面置換算法(opt,lru,fifo,clock)實現

選擇調出頁面的算法就稱為頁面置換算法。好的頁面置換算法應有較低的頁面更換頻率&#xff0c;也就是說&#xff0c;應將以后不會再訪問或者以后較長時間內不會再訪問的頁面先調出。 常見的置換算法有以下四種&#xff08;以下來自操作系統課本&#xff09;。 1. 最佳置換算法(…

(六)Linux之設備驅動模型(續)

前面我們學習了雜項設備驅動模型、早期經典字符設備驅動模型,這一小節來講解Linux中的標準字符設備驅動。 目錄&#xff08;一&#xff09;為什么引入標準字符設備驅動模型&#xff08;二&#xff09;相關接口&#xff08;三&#xff09;注冊流程&#xff08;四&#xff09;程序…

N個數依次入棧,出棧順序有多少種?

對于每一個數來說&#xff0c;必須進棧一次、出棧一次。我們把進棧設為狀態‘1’&#xff0c;出棧設為狀態‘0’。n個數的所有狀態對應n個1和n個0組成的2n位二進制數。由于等待入棧的操作數按照1‥n的順序排列、入棧的操作數b大于等于出棧的操作數a(a≤b)&#xff0c;因此輸出序…

(七)linux函數接口的使用

前面我們講解了字符設備的驅動模型&#xff0c;有了前面的基礎后&#xff0c;今天學習函數接口就比較容易了 目錄&#xff08;一&#xff09;open函數接口&#xff08;二&#xff09;read函數接口&#xff08;三&#xff09;lseek函數接口&#xff08;四&#xff09;用戶空間和…

(八)linux驅動之ioctl的使用

這篇文章給大家講解一下ioctl的簡單使用&#xff0c;關于ioctl更詳細的教程后面有機會單獨寫出來 &#xff08;一&#xff09;什么是ioctl ioctl是設備驅動程序中對設備的I/O通道進行管理的函數。所謂對I/O通道進行管理&#xff0c;就是對設備的一些特性進行控制&#xff0c;例…

(九)linux中斷編程

目錄&#xff08;一&#xff09;linux中斷的介紹&#xff08;二&#xff09;內核中斷的操作過程&#xff08;三&#xff09;實例代碼&#xff08;一&#xff09;linux中斷的介紹 linux內核中的中斷通過中斷子系統來管理。linux系統中有專門的中斷子系統&#xff0c;原理很復雜…

網絡爬蟲(1)

參考&#xff1a;http://www.cnblogs.com/dongkuo/p/4851735.html算法分析我們現在從需求中提取關鍵詞來逐步分析問題。 首先是“種子節點”。它就是一個或多個在爬蟲程序運行前手動給出的URL&#xff08;網址&#xff09;&#xff0c;爬蟲正是下載并解析這些種子URL指向的頁面…

(十)Linux之等待隊列

&#xff08;一&#xff09;阻塞和非阻塞 阻塞&#xff1a;執行設備操作時&#xff0c;若不能獲得資源&#xff0c;則掛起進程進入休眠直到滿足可操作的條件后再操作。 非阻塞&#xff1a;進程在不能進行設備操作時&#xff0c;并不掛起&#xff0c;它要么放棄&#xff0c;要么…

(十一)linux之poll輪詢

目錄&#xff08;一&#xff09;poll輪詢的作用&#xff08;二&#xff09;poll輪詢相關的接口&#xff08;三&#xff09;poll使用流程&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;poll輪詢的作用 以阻塞的方式打開文件&#xff0c;那么對多個文件讀寫時&a…

校驗碼(海明校驗,CRC冗余校驗,奇偶校驗)

循環冗余校驗碼 CRC碼利用生成多項式為k個數據位產生r個校驗位進行編碼,其編碼長度為nkr所以又稱 (n,k)碼. CRC碼廣泛應用于數據通信領域和磁介質存儲系統中. CRC理論非常復雜,一般書就給個例題,講講方法.現在簡單介紹下它的原理: 在k位信息碼后接r位校驗碼,對于一個給定的(n,k…

(十二)linux內核定時器

目錄&#xff08;一&#xff09;內核定時器介紹&#xff08;二&#xff09;內核定時器相關接口&#xff08;三&#xff09;使用步驟&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;內核定時器介紹 內核定時器并不是用來簡單的定時操作&#xff0c;而是在定時時…

java Proxy(代理機制)

我們知道Spring主要有兩大思想&#xff0c;一個是IoC&#xff0c;另一個就是AOP&#xff0c;對于IoC&#xff0c;依賴注入就不用多說了&#xff0c;而對于Spring的核心AOP來說&#xff0c;我們不但要知道怎么通過AOP來滿足的我們的功能&#xff0c;我們更需要學習的是其底層是怎…

(十三)linux中斷底半部分處理機制

這篇文章介紹一下linux中斷的底半部分的tasklet和workquene兩種處理機制&#xff0c;其中tasklet中不能有延時函數&#xff0c;workquene的處理函數可以加入延時操作 目錄&#xff08;一&#xff09;tasklet小任務處理機制&#xff08;1&#xff09;tasklet相關函數接口&#x…

Codeforces Round #326 (Div. 2) B. Pasha and Phone C. Duff and Weight Lifting

B. Pasha and PhonePasha has recently bought a new phone jPager and started adding his friends phone numbers there. Each phone number consists of exactly n digits. Also Pasha has a number k and two sequences of length n?/?k (n is divisible by k) a1,?a2,?…

vmware中裝的ubuntu上不了網

本文章針對橋接方式進行講解&#xff0c;如果需要另外兩種連接方式請參考文末給出的鏈接 &#xff08;一&#xff09;問題 主機和虛擬機可以相互ping通&#xff0c;但是卻不能ping網址 &#xff08;二&#xff09;解決辦法 vmware為我們提供了三種網絡工作模式&#xff0c;…

document.getElementById()與 $()區別

document.getElementById()返回的是DOM對象&#xff0c;而$()返回的是jQuery對象 什么是jQuery對象&#xff1f; ---就是通過jQuery包裝DOM對象后產生的對象。jQuery對象是jQuery獨有的&#xff0c;其可以使用jQuery里的方法。 比如&#xff1a; $("#test").html() 意…