以前咱們寫的代碼都是直接編譯到內核中,這樣每次都要進行內核的從新編譯,而且還要刷機纔可以看到效果,非常麻煩.這回咱們來學習一下如何直接編譯一段代碼,以模塊的方式安裝到內核執行:linux
一個文件編譯成一個內核模塊:vim
找一個文件夾:touch module_test1.c Makefile數組
vim module_test1.cide
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 5 //當模塊安裝的時候執行 6 static __init int test_init(void) 7 { 8 printk("test_init\n"); 9 return 0; 10 } 11 //當模塊卸載的時候執行 12 static __exit int test_exit(void) 13 { 14 printk("test_exit\n"); 15 return 0; 16 } 17 //註冊這兩個函數 18 module_init(test_init); 19 module_exit(test_exit); 20 //聲明開源規則 21 MODULE_LICENSE("GPL");
vim Makefile函數
1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5 #指定咱們板子上用的內核路徑,使用這個內核編譯的代碼才能成功運行在咱們的板子上. 2 obj-m += module.o #生成module.ko 但咱們寫module.o就能夠 3 module-objs=module_test1.o #這裏寫要編譯文件 4 #obj-m +=module_test1.o #這是單文件的編譯:上面兩行是多文件的編譯,更加方便 5 6 all: 7 make -C $(LINUX_SRC) M=`pwd` modules 8 clean: 9 make -C $(LINUX_SRC) M=`pwd` modules clean
make 生成 module.ko學習
cp module.ko /myroot/liuye 即nfs共享路徑下 運行看下效果吧this
root@board liuye_dir#insmod module.ko [ 3817.370000] test_init root@board liuye_dir#lsmod Module Size Used by Tainted: G module 740 0 root@board liuye_dir#rmmod module.ko [ 3821.550000] test_exit root@board liuye_dir#
/*****************************************************************************************************************************************************************************************************/spa
多個文件編譯成一個內核模塊:code
touch module_test1.c module_test2.c Makefileblog
vim module_test1.c 調用module_test2.c內的函數
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 //內核代碼中不容許有警告,由於在編譯的時候多是警告,可是在邏輯尚有多是個錯誤 5 extern int my_print(int no); 6 //當模塊安裝的時候執行 7 static __init int test_init(void) 8 { 9 printk("test_init\n"); 10 my_print(5); 11 return 0; 12 } 13 //當模塊卸載的時候執行 14 static __exit int test_exit(void) 15 { 16 printk("test_exit\n"); 17 return 0; 18 } 19 //註冊這兩個函數 20 module_init(test_init); 21 module_exit(test_exit); 22 //聲明開源規則 23 MODULE_LICENSE("GPL");
vim module_test2.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 int my_print(int no) 5 { 6 int i; 7 for(i=0;i<no;i++) 8 { 9 printk("no=%d\n",no); 10 } 11 return 100; 12 }
vim Makefile
1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5 2 obj-m += module.o #生成module.ko 但咱們寫module.o就能夠 3 module-objs=module_test1.o module_test2.o #這裏寫要編譯的文件 4 #obj-m +=module_test1.o #這是單文件的編譯:上面兩行是多文件的編譯,更加方便 5 6 all: 7 make -C $(LINUX_SRC) M=`pwd` modules 8 clean: 9 make -C $(LINUX_SRC) M=`pwd` modules clean
make 生成module.ko 到開發板上安裝查看卸載
root@board liuye_dir#insmod module.ko [ 5324.040000] test_init [ 5324.040000] no=5 [ 5324.040000] no=5 [ 5324.040000] no=5 [ 5324.040000] no=5 [ 5324.040000] no=5 root@board liuye_dir#lsmod Module Size Used by Tainted: G module 913 0 root@board liuye_dir#rmmod module.ko [ 5327.515000] test_exit root@board liuye_dir#
/*****************************************************************************************************************************************************************************************************/
多個文件編譯成多個內核模塊:
vim module_test1.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 //內核代碼中不容許有警告,由於在編譯的時候多是警告,可是在邏輯尚有多是個錯誤 5 extern int my_print(int no); 6 //當模塊安裝的時候執行 7 static __init int test_init(void) 8 { 9 printk("test_init\n"); 10 my_print(5); 11 return 0; 12 } 13 //當模塊卸載的時候執行 14 static __exit int test_exit(void) 15 { 16 printk("test_exit\n"); 17 return 0; 18 } 19 //註冊這兩個函數 20 module_init(test_init); 21 module_exit(test_exit); 22 //聲明開源規則 23 MODULE_LICENSE("GPL");
vim module_test2.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 static __init int test_init(void) 5 { 6 return 0; 7 } 8 static __exit int test_exit(void) 9 { 10 return 0; 11 } 12 int my_print(int no) 13 { 14 int i; 15 for(i=0;i<no;i++) 16 { 17 printk("no=%d\n",no); 18 } 19 return 100; 20 } 21 //模塊之間的關係要進行符號導出 22 //模塊1調用了模塊2內部的函數my_print,雖然函數以前沒有添加static修飾,可是在模塊之間調用,至關於的添加了static修飾,因此該函數不支持其餘模塊的調用,
只支持當前文件和當前模塊的調用.因此模塊2安裝完成,模塊1依然insmod不上,爲了解決模塊1依賴模塊2的問題,因此要進行符號導出.
咱們寫的驅動程序都須要調用內核提供的方法,內核裏面的方法都是通過符號導出的. 23 //其中module_init和module_exit是宏實現的:宏定義在:#include<linux/module.h>中 24 EXPORT_SYMBOL(my_print); 25 module_init(test_init); 26 module_exit(test_exit); 27 MODULE_LICENSE("GPL"); ~
vim Makefile
1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5 2 #obj-m += module.o #生成module.ko 但咱們寫module.o就能夠 3 #module-objs=module_test1.o module_test2.o #這裏寫要編譯文件 4 obj-m +=module_test1.o module_test2.o #這是單文件的編譯會生成多個ko:上面兩行是多文件的編譯,更加方便 5 6 all: 7 make -C $(LINUX_SRC) M=`pwd` modules 8 clean: 9 make -C $(LINUX_SRC) M=`pwd` modules clean
在安裝的時候要先安裝模塊2在安裝模塊一,在卸載的時候要先卸載模塊1再卸載模塊2;
解釋depmod:請參見另外一片文章
modprobe:
以及內核傳參數的代碼請查看另外一篇文章:
/*****************************************************************************************************************************************************************************************************/
1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5 2 #obj-m += module.o #生成module.ko 但咱們寫module.o就能夠 3 #module-objs=param.o #這裏寫要編譯文件 4 obj-m +=param.o param1.o #這是單文件的編譯:上面兩行是多文件的編譯,更加方便 5 6 all: 7 make -C $(LINUX_SRC) M=`pwd` modules 8 clean: 9 make -C $(LINUX_SRC) M=`pwd` modules clean
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 5 static __init int test1_init(void) 6 { 7 printk("this is liuye test1_init\n"); 8 return 0; 9 } 10 static __exit void test1_exit(void) 11 { 12 printk("this is liuye test1_exit\n"); 13 } 14 15 module_init(test1_init); 16 module_exit(test1_exit); 17 MODULE_LICENSE("GPL"); 18 void my_print(int no) 19 { 20 printk("no = %d\n",no); 21 } 22 EXPORT_SYMBOL(my_print);
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 extern void my_print(int name); 5 6 int name=0; 7 char *buf; 8 bool boolc; 9 int arr[10]; 10 int len; 11 //module_param_named(name,name,int,0); 12 //module_param_named(buf,buf,charp,0); 13 //module_param_named(boolc,boolc,bool,0); 14 15 module_param(name,int,0660); 16 module_param(buf,charp,0660); 17 module_param(boolc,bool,0660); 18 module_param_array(arr,int,&len,0660); 19 static __init int test_init(void) 20 { 21 int i; 22 printk("this is liuye test_init\n"); 23 // my_print(name); 24 printk("name =%d\n",name); 25 printk("buf =%s\n",buf); 26 printk("boolc =%d\n",boolc); 27 for(i=0;i<len;i++) 28 { 29 printk("arr[%d]=[%d]\n",i,arr[i]); 30 } 31 printk("len =%d\n",len); //這裏的長度,等於實際輸入的數組元素個數 32 my_print(333333) 33 return 0; 34 } 35 static __exit void test_exit(void) 36 { 37 int i; 38 printk("this is liuye test_exit\n"); 39 // my_print(name); 40 printk("name =%d\n",name); 41 printk("buf =%s\n",buf); 42 printk("boolc =%d\n",boolc); 43 for(i=0;i<len;i++) 44 { 45 printk("arr[%d]=[%d]\n",i,arr[i]); 46 } 47 printk("len =%d\n",len); //這裏的長度,等於實際輸入的數組元素個數 48 49 } 50 51 module_init(test_init); 52 module_exit(test_exit); 53 MODULE_LICENSE("GPL");