首先,我們去下載一份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檔。即可卸載。

    全站熱搜

    立你斯 發表在 痞客邦 留言(0) 人氣()