1 內核模塊linux
Linux內核的總體結構很是龐大,其包含的組件也很是多,若是把全部的組件都編譯進內核文件,即:zImage或bzImage,但這樣會導致一個問題:佔用內存過多。數組
因此就須要動態的添加某些組件,這些組件就是內核模塊。特色:模塊自己並不被編譯到內核文件(zImage或bzImage);能夠根據需求,在內核運行期間動態的安裝或卸載。函數
安裝:insmodui
insmod /home/dongry/dnw_usb.kospa
卸載:rmmod.net
rmmod dnw_usb設計
查看:lsmod指針
lsmodcode
2 內核模塊的設計與編寫blog
/************************************************* *file_name:helloworld.c *************************************************/ #include <linux/init.h> #include <linux/module.h> static int hello_init(void) { printk(KERN_WARING"hello world\n"); return 0; } static void hello_exit(void) { printk(KERN_INFO"goodbye world\n"); } module_init(hello_init); module_exit(hello_init);
printk的用法:https://blog.csdn.net/eydwyz/article/details/53044863
必要的頭文件:<linux/init.h> <linux/module.h>
module_init()內核模塊的入口 即加載函數
module_exit()內核模塊的出口 即卸載函數
當insmod安裝helloworld.ko的時候module_init(hello_init)就會被調用
當rmmod卸載helloworld.ko的時候module_exit(hello_exit)就會被調用
2.1 內核模塊必要元素框圖
內核中打印用printk,應用程序用printf
/*********************************** *filename:Makefile ************************************/ obj-m := helloworld.o KDIR := /home/dongry/mini2440/mini2440 /*開發板內核代碼路徑*/ all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm clean: rm -f *.o *.ko *.order *.symvers
/*********************************** *filename:Makefile *function:can in x86 kernel run ************************************/ obj-m := helloworld.o KDIR := /home/dongry/x86/linux-4.19.30 /*開發板內核代碼路徑*/ all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.o *.ko *.order *.symvers
make含有helloworld.c和Makefile的文件獲得helloworld.ko文件;若是是通過編譯的x86內核後能夠直接在Terminal窗口運行insmod、lsmod、rmmod;若是是通過編譯的arm內核需在secure crt上連接開發板才能運行。
3 模塊聲明
a)MODULE_LICENSE("遵照的協議"):聲明該模塊遵照的許可證協議,如"GPL"、"GPL v2"
b)MODULE_AUTHOR("做者"):聲明模塊的做者
c)MODULE_VERSION("版本"):聲明模塊的版本信息
d)MODULE_DESCRIPTION("模塊功能描述"):聲明模塊的功能
/************************************************* *file_name:helloworld.c *************************************************/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); //模塊聲明 static int hello_init(void) { printk(KERN_WARING"hello world\n"); return 0; } static void hello_exit(void) { printk(KERN_INFO"goodbye world\n"); } module_init(hello_init); module_exit(hello_init);
4 模塊參數
咱們能夠在加載內核模塊的時候向其傳遞參數,以讓同一代碼達到不一樣的效果。經過宏module_param指定保存模塊參數的變量。模塊參數用於在加載模塊時傳遞參數給模塊。
格式:module_param(name,type,perm)
a)name:變量的名稱
b)type:變量的類型,數據類型內核支持模塊參數類型有:bool、invbool(bool的發轉,true變爲false,false變爲true)、charp(char類型指針值)、int、long、short、uint、ulong、ushort、
c)perm:訪問權限,常見的訪問許可值一般爲S_IRUGO(讀權限)和S_IWUSR(寫權限)。一般狀況下將他們按位或
同時咱們也能夠用下面的宏聲明數組:
Module_param_array(name,type,num,perm)
/************************************************* *file_name:helloworld.c *************************************************/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); //模塊聲明 int a=3; charp *p; module_param(a,int,S_IRUGO | S_IWUSR); //加載一個整型參數 module_param(P,charp,S_IRUGO | S_IWUSR); //加載一個字符型參數 static int hello_init(void) { printk(KERN_WARING"hello world\n"); printk("a=%d\n",a); printf("p is %s\n",p); return 0; } static void hello_exit(void) { printk(KERN_INFO"goodbye world\n"); } module_init(hello_init); module_exit(hello_init);
/*結果顯示*/ /*********************************************************/ #insmod helloworld.ko a=10 p=abcd hello,world! a=10 p is abcd
5 模塊符號導出
當一個模塊要使用另外一個模塊的函數(變量)的時候,要使用EXPORT_SYMBOL(符號名)或者EXPORT_SYMBOL_GPL(符號名)來申明。
注:EXPORT_SYMBOL_GPL()只適用於遵循GPL協議的模塊
/********************************************** *filename:add.c *********************************************/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); int add(int a,int b) { return a+b; } static int add_init(void) { return 0; } static void add_exit(void) { }
EXPORT_SYMBOL(add); //能夠將add導出給其餘函數 module_init(add_init); module_exit(add_exit);
/************************************************* *file_name:helloworld.c *function:calling add.c *************************************************/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("GPL"); //模塊聲明 extern add(int a,int b); int a=3; charp *p; module_param(a,int,S_IRUGO | S_IWUSR); //加載一個整型參數 module_param(P,charp,S_IRUGO | S_IWUSR); //加載一個字符型參數 static int hello_init(void) { printk(KERN_WARING"hello world\n"); printk("a=%d\n",a); printf("p is %s\n",p); return 0; } static void hello_exit(void) { add(1,4); printk(KERN_INFO"goodbye world\n"); } module_init(hello_init); module_exit(hello_init);
/*********************************** *filename:Makefile ************************************/ obj-m := helloworld.o add.o KDIR := /home/dongry/mini2440/mini2440 /*開發板內核代碼路徑*/ all: make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm clean: rm -f *.o *.ko *.order *.symvers
/*結果顯示*/ /*********************************************************/ /***************先加載add.ko,後加載helloworld.ko***************/ #insmod add.ko #insmod helloworld.ko a=10 p=abcd hello,world! a=10 p is abcd