轉自:http://www.cnblogs.com/yiru/archive/2012/11/26/2789681.html(博主:勒達與天鵝)
僅供學習參考
在學習ldd需要搭建linux驅動開發環境,在網上找到這篇文章http://xuxd32.blog.163.com/blog/static/481219332011814112045622/
按照上面這篇文章的步驟會遇到許多困難,經過近2天的摸索和修改之後,終於成功。
以下為修正後的文章。
在看《Linux Device Driver Third Edition》的時候,作者其中提到Setting Up Your Test System。他只是指出:為2.6.X編寫模塊,首先,要求你在Linux系統上構建和配置內核樹,對於2.6版本的內核來說,已有的頭文件已經足夠了,但是2.6的模塊鏈接著內核源碼樹中的對象文件。這樣模塊加載器將更健壯,但是也要求這些對象文件存在。所以驅動開發的第一件事情就是構建內核源碼樹。
他沒有提到如何構建,我從網上找了一些資料,構建了自己的內核樹,寫出來大家分享一下,本人用的是Ubuntu Linux 10.10 裝在虛擬機裡面,要求你的虛擬機硬盤容量最少不低於10G,本人10G,仍有提示硬盤容量不夠,但是還是完成了內核樹的構建,15G硬盤容量應該夠了。
首先查看自己的linux內核的版本,在終端中輸入: uname -r
可以看到自己的內核版本,我的內核版本為:2.6.32-35-generic
然後進入 usr/src/下查看是否有linux-source 文件,一般是沒有的,至少我的ubuntu沒有
沒有就去網上查找,在終端中輸入: apt-cache search linux-source
可以看到結果:
linux-source - Linux kernel source with Ubuntu patches
linux-source-2.6.35 - Linux kernel source for version 2.6.35 with Ubuntu patches
選擇同自己內核相應的linux-source版本安裝。在終端中輸入:
sudo apt-get install linux-source-2.6.35
下載完畢後在/usr/src/下有個名為linux-source-2.6.35 的文件夾,在該文件夾裡面有linux-source-2.6.35.tar.bz2 ,解壓到/usr/src/linux-source-2.6.35/目錄下。
解壓方法,在終端中輸入: sudo -i 切換到根用戶下,定位到/usr/src/linux-source-2.6.35/目錄下,在終端中輸入:tar jxvf linux-source-2.6.35.tar.bz2
解壓得到文件源代碼文件,該源代碼文件夾名稱為linux-source-2.6.35,進入該目錄,注意此時在終端中應該是這樣的:
開始配置內核,選擇最快的原版的配置(默認)方式:在終端中輸入:make oldconfig
完成後,先去配置/usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile文件。
不然會出現ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directory錯誤
在根用戶下打開該Makefile文件,將其中的PWD=$(shell pwd)剪切到ifeq ($(KERNELRELEASE),) 前面。然後保存。
然後編譯模塊,定位到源代碼文件夾下,在終端中輸入: make modules
等待將近1個小時,該編譯完成。完成之後,安裝模塊,在終端中輸入:make modules_install
至此,源碼樹構建完成,重啟系統,
將《Linux Device Driver Third Edition》中的第一個例子運行下吧。
文中代碼:helloworld.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int hello_init(void){
printk(KERN_ALERT "hello world!\n");
return 0;
}
static int hello_exit(void){
printk(KERN_ALERT "Goodbye cruel world!\n");
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
Makefile文件內容:
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.symvers *.order
endif
編譯,在終端中輸入:make
make -C /lib/modules/2.6.32-35-generic/build M=/source/test/ldd
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-35-generic'
LD /source/test/ldd/built-in.o
CC [M] /source/test/ldd/hello.o
/source/test/ldd/hello.c: In function '__exittest':
/source/test/ldd/hello.c:16: warning: return from incompatible pointer type
Building modules, stage 2.
MODPOST 1 modules
CC /source/test/ldd/hello.mod.o
LD [M] /source/test/ldd/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-2.6.32-35-generic'
查看生成的模塊 modinfo hello.ko
加載模塊 insmod hello.ko
未提示出錯。成功
查看已加載模塊 lsmod
刪除模塊 rmmod hello.ko
為什麼加載和刪除模塊時沒有顯示源碼中printk的打印信息?書中說明,如果不出現在終端,則會寫進 syslog 文件中
cat /var/log/syslog |grep world(或者全部打印,看最後兩行)
Nov 28 11:07:47 ubuntu64 kernel: [ 6942.233442] hello world!
Nov 28 11:08:00 ubuntu64 kernel: [ 6955.202296] Goodbye cruel world!
啊哈哈哈哈哈哈哈哈,成功!!!!
驅動開發實驗環境搭建完成。