今天是一個值得紀念的日子,我也不知道我花了多長時間才編譯成功!在編寫這個驅動的過程中,真的體會到驅動編程不是那麼簡單的~,現在有點小小的激動,真的,很不容易啊~我把整個過程在重復一遍吧!
在編寫這個驅動的過程中參考了網上的很多文檔,最終的結果是弄的我頭都暈了,每個人寫的都不一樣,其實我現在還有一些概念不是很清楚。
1:到底丫的什麼是內核源碼樹?
2:為什麼要編譯內核源碼樹?
1:內核源碼樹我現在的理解就是整個linux內核源代碼,它是編譯驅動的前提。Ubuntu系統默認情況下是沒有的,
內核源碼樹是要自己下載的。
2:驅動最終以*.ko的形式生成,insmod的本質就是將ko文件與運行的內核進行鏈接的過程。類似於編譯helloworld的鏈接過程。
鏈接必然需要先進行編譯,以便確定所需的外部符號(EXPORT_SYMBOLS)是否存在,因為有些符號(函數或全局變量)在
內核中。在驅動中如果使用到這些符號,必須預留一個位置,insmod時進一步確定這些符號的具體位置(符號綁定)。
如果內核都沒有編譯過,怎麼知道這些符號有沒有編入內核中
Hello World驅動實現全過程
1:首先要查看自己系統是使用的內核版本
www.linuxidc.com @linux:~$ uname -r
3.2.0-34-generic-pae //我用的是ubuntu12.04版本的,比較高
如果系統自動安裝了源碼。在/usr/src目錄下面會有對應的使用的版本,我那個版本沒有,我是自己下載的
www.linuxidc.com @linux:/usr/src$ ls
linux-headers-3.2.0-34 linux-source-3.2.0(我下載的)
linux-headers-3.2.0-34-generic-pae
如果沒有源碼,查看一下可以下載的源碼包(不要使用超級用戶使用此命令,他會提示沒有這個命令)
#apt-cache search linux-source
www.linuxidc.com @linux:/usr/src$ apt-cache search linux-source
linux-source - Linux kernel source with Ubuntu patches
linux-source-3.2.0 - Linux kernel source for version 3.2.0 with Ubuntu patches
2:然後下載linux-source-3.2.0
#sudo apt-get install linux-source-3.2.0
下載完成之後,會在/usr/src下,文件名為linux-source-3.2.0.tar.bz2這個壓縮包,解壓之後就可以得到整個源代碼
# sudo tar jxvf linux-source-3.2.0.tar.bz2
解壓之後會生成一個新的目錄/usr/src/linux-source-3.2.0,現在所有的源代碼都在裡面
3:現在開始配置內核,有三種選擇選擇方式1:make oldconfig 2:make menuconfig 3:make xconfig
我選擇的是最快的配置原版的配置方法
#sudo make oldconfig
(如果配置的過程中出現問題,原因是因為你沒有下載配置環境的那個依賴的庫文件,可以自己下載)
配置完成之後就要開始對內核進行編譯了
4:編譯內核
#sudo make
這個過程很漫長,建議去做做別別的事情吧~,我大概花了一個多小時,吃完晚飯回來就ok了
#sudo make zImage
編譯內核的結果最終出現了幾個錯誤,但最終對那個Hello World 沒有造成影響
執行結束之後,會在當前目錄下面生成一個新的文件:vmlinux
5:然後就是編譯模塊了
#sudo make modules
6:安裝模塊
#sudo make modules_install
執行結束之後,會在/lib/modules下生成一個新的目錄/lib/modules/3.2.31/
在隨後的編譯模塊文件時,需要用到這個路徑下的build目錄。到這一不,內核就編譯完成了
好了,下了很長時間的Hello World 程序現在終於可以派上用場了
我的Hello World在/hoem/xiongyao/下面
//hello.c
#include<linux/init.h> //初始換函數
#include<linux/kernel.h> //內核頭文件
#include<linux/module.h> //模塊的頭文件
MODULE_LICENSE("Xiongyao BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALTER"Hello, world\n"); //模塊運行在內核態,不能使用用戶態C庫函數中的printf函數,而要使用printk函數
//打印調試信息
return 0;
}
static int hello_exit(void)
{
printk("KERN_ALTER"Goodbye,Hello world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile 文件
obj-m:=hello.o //生成目標文件
KERNELDIR:=/lib/modules/3.2.31/build
PWD :=$(shell pwd)
modules:
(這裡要用一個tab鍵)$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules
(這裡用一個tab鍵) $(MAKE) -C $(KERNELDIR)M=$(PWD) modules_install
最好關鍵的一步到了,所有准備就緒,進入makefile的那個目錄
www.linuxidc.com @linux:~$ sudo make
make -C /lib/modules/3.2.31/build M=/home/xiongyao
make[1]: 正在進入目錄 `/usr/src/linux-source-3.2.0/linux-source-3.2.0'
LD /home/xiongyao/built-in.o
CC [M] /home/xiongyao/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/xiongyao/hello.mod.o
LD [M] /home/xiongyao/hello.ko
make[1]:正在離開目錄 `/usr/src/linux-source-3.2.0/linux-source-3.2.0'
上面證明已經成功了
然後加載模塊
#sudo insmod ./hello.ko
本應該會在終端顯示hello,world 但是終端什麼也沒有顯示(以後在去解決)
查看加載模塊
#sudo lsmod
裡面已經生成了hello
hello 2560 0
^_^,已經加載上了
刪除模塊
#sudo rmmod hello
那麼程序的輸出到底在哪裡呢?在網上看到,如果不出現在終端,則會下進syslog中
#cat /var/log/syslog |grep world
#Hello,world
#Goodbye,linux world
現在所有工作全部完成了,希望做這個Hello World 是我進入linux驅動的第一步~,相信你們也能編譯的!成功的編譯成功的。