首先,我們去下載一份ldd3的配套源碼,下面是我分享的一份代碼,大家可以下載使用:http://yunpan.cn/lk/sV2ZrN6JFEKKW?sid=301
對源碼進行解壓,裏面會有好幾個目錄,我們現在要關心的就是scull這個目錄,下面的操作都會在這裏進行。
root@yafeng-VirtualBox:/examples# ls
include LICENSE misc-modules pci scull sculld scullv shortprint skull tty
lddbus Makefile misc-progs sbull scullc scullp short simple snull usb
root@yafeng-VirtualBox:/examples#
再者,我們來看看我們要編譯的平臺的是怎麼樣的一個平臺:
root@yafeng-VirtualBox:/# uname -a
Linux yafeng-VirtualBox 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux
root@yafeng-VirtualBox:/#
通過上面的列印,我們可以知道是3.0.0.12的內核。
好了,萬事俱備,只欠東風。下面就開始編譯吧。我們總的思路就是一步步的make,然後根據提示一步步的解決啊!
一.習慣性地由make開始,我們會看到下面的錯誤:
root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
scripts/Makefile.build:49: *** CFLAGS was changed in "/examples/scull/Makefile". Fix it to use EXTRA_CFLAGS. Stop.
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
解決方法:循著錯誤提示,我們將Makefile檔中的CFLAGS都改為了EXTRA_CFLAGS,共三處。
二.繼續make:
root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
CC [M] /examples/scull/main.o
/examples/scull/main.c:17:26: fatal error: linux/config.h: No such file or directory
compilation terminated.
make[2]: *** [/examples/scull/main.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
root@yafeng-VirtualBox:/examples/scull#
解決方法:根據提示,我們來到main.c文件。將#include <linux/config.h>直接刪掉即可,因為config.h這個頭檔貌似在2.6.19的內核版本後就沒有了。
三.走著:
root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
CC [M] /examples/scull/main.o
/examples/scull/main.c:555:2: error: unknown field ‘ioctl’ specified in initializer
/examples/scull/main.c:555:2: warning: initialization from incompatible pointer type [enabled by default]
/examples/scull/main.c:555:2: warning: (near initialization for ‘scull_fops.aio_read’) [enabled by default]
/examples/scull/main.c: In function ‘scull_init_module’:
/examples/scull/main.c:651:3: error: implicit declaration of function ‘init_MUTEX’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make[2]: *** [/examples/scull/main.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
這裏有兩個錯誤:
1.ioctl。
因為在內核2.6.36中已經完全刪除了struct file_operations中的ioctl函數指標,取而代之的是unlocked_ioctl。
這種改動在應用程式中是相容的,但是在驅動程式中,我們可以發現,兩者是不能相容的,參數中少了inode,所以在驅動程式中必須加以改變,不然就會影響cmd參數的變化。
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
long scull_ioctl (struct file *filp, unsigned int cmd, unsigned long arg);
解決辦法:1.就是將源代碼中的scull_ioctl的函數頭改為上面的第二種形式。
2.所有file_operations結構體中的ioctl函數指標。改為unlocked_ioctl。
改動比較多,各個.c和.h檔中幾乎都會涉及到。
2.init_MUTEX.
在2.6.24的內核中,我們可以發現如下定義:
static inline void init_MUTEX (struct semaphore *sem)
{
sema_init(sem, 1);
}
但是在2.6.25以後就已經不再使用這個宏了。
解決方法:我們就直接用sema_init(struct semaphore *sem, int val);來代替它。
同樣這裏的改動比較多,因而還是要仔細一點。
四.堅持著:
root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
CC [M] /examples/scull/main.o
CC [M] /examples/scull/pipe.o
/examples/scull/pipe.c: In function ‘scull_p_read’:
/examples/scull/pipe.c:131:7: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c:131:7: note: each undeclared identifier is reported only once for each function it appears in
/examples/scull/pipe.c:131:3: error: implicit declaration of function ‘signal_pending’ [-Werror=implicit-function-declaration]
/examples/scull/pipe.c:131:3: error: implicit declaration of function ‘schedule’ [-Werror=implicit-function-declaration]
/examples/scull/pipe.c: In function ‘scull_getwritespace’:
/examples/scull/pipe.c:168:38: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c: In function ‘scull_p_write’:
/examples/scull/pipe.c:219:2: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c:223:34: error: ‘SIGIO’ undeclared (first use in this function)
/examples/scull/pipe.c:223:41: error: ‘POLL_IN’ undeclared (first use in this function)
cc1: some warnings being treated as errors
make[2]: *** [/examples/scull/pipe.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
看錯誤提示,這裏主要就是TASK_INTERRUPTIBLE宏沒有定義。這是最好辦的。
解決方法:到源碼中rgrep一下唄,看它在哪個頭文件中,就將它加上。
一般來說,系統的源代碼都會放在:/usr/src/XXX-generic目錄下。
最後,發現TASK_INTERRUPTIBLE定義在linux/sched.h中;因而,只需要在需要的.c文件中添加#include <linunx/sched.h>即可。
五.勝利就在眼前:
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
CC [M] /examples/scull/access.o
/examples/scull/access.c:99:34: error: ‘SPIN_LOCK_UNLOCKED’ undeclared here (not in a function)
/examples/scull/access.c: In function ‘scull_u_open’:
/examples/scull/access.c:107:29: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c:108:29: error: ‘struct task_struct’ has no member named ‘euid’
/examples/scull/access.c:115:26: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c: In function ‘scull_w_available’:
/examples/scull/access.c:166:27: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c:167:27: error: ‘struct task_struct’ has no member named ‘euid’
/examples/scull/access.c: In function ‘scull_w_open’:
/examples/scull/access.c:185:26: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c: In function ‘scull_w_available’:
/examples/scull/access.c:169:1: warning: control reaches end of non-void function [-Wreturn-type]
make[2]: *** [/examples/scull/access.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
這裏也是有兩個問題哦。
1.struct task_struct。
錯誤提示沒有uid和euid。查看源代碼發現還真沒有,不過覺得有點不可思議。繼續搜索……發現在2.6.35內核中,就將這兩個成員放到const struct cred *cred成員中了 。也就是被降級了。
解決方法:很好辦,只要像下面一樣,在uid和euid引用的地方再加一層cred,不就OK了。
current->uid-----》current->cred->uid
current->euid-----》current->cred->euid
2.SPIN_LOCK_UNLOCKED
很明顯,這又是一個未定巨集的錯誤。但是我們又發現了這個宏在2.6.19的內核中就已經被棄用.
解決方法:在我們3.0.0.12的內核中要換一個宏來代替它----DEFINE_SPINLOCK(X);替代方法如下:
static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;----> static DEFINE_SPINLOCK(scull_u_lock);
注意要在每個.c檔中都將SPIN_LOCK_UNLOCKED進行如上替換。
六.陽光總在風雨後:
root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
CC [M] /examples/scull/main.o
CC [M] /examples/scull/pipe.o
CC [M] /examples/scull/access.o
LD [M] /examples/scull/scull.o
Building modules, stage 2.
MODPOST 1 modules
CC /examples/scull/scull.mod.o
LD [M] /examples/scull/scull.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
經過這麼多的修改,終於將scull編譯好了。
接下來,你就可以用實驗來好好鞏固你在書本上看到的知識了哦!以後我也可以用這個來講解驅動知識了,不會那麼的枯燥。
最後,我們來看看如何載入scull。
看到有scull_load和scull_unload了吧。對的,載入就用scull_load,反之卸載就用scull_unload。
要是兩個檔沒有執行許可權的,就先給他們chmod一個執行許可權哦!載入後如下所示:
root@yafeng-VirtualBox:/examples/scull# chmod +x scull_*
root@yafeng-VirtualBox:/examples/scull# ls
access.c main.c Makefile Module.symvers pipe.o scull.init scull_load scull.mod.o scull_unload
access.o main.o modules.order pipe.c scull.h scull.ko scull.mod.c scull.o
root@yafeng-VirtualBox:/examples/scull# ./scull_load
root@yafeng-VirtualBox:/examples/scull#
用cat /proc/devices應該就能scull*的幾項列印,這就說明設備已經掛載好了。
當不使用scull時,就指向scull_unload檔。即可卸載。
留言列表