Linux驅(qū)動(dòng)開發(fā)筆記(三):基于ubuntu的helloworld驅(qū)動(dòng)源碼編寫、makefile編寫以及驅(qū)
前言
??前面學(xué)習(xí)了驅(qū)動(dòng)的基礎(chǔ)框架,上一篇編譯了gcc7.3.0,那么為了方便很好的熟悉流程,本篇,將使用ubuntu18.04,直接編譯ubuntu18.04的驅(qū)動(dòng),然后做好本篇文章的相關(guān)實(shí)戰(zhàn)測(cè)試。
Ubuntu虛擬機(jī)準(zhǔn)備
步驟一:安裝虛擬機(jī)
??本次使用之前rk3568的ubuntu18.04,筆者沒有重新弄了,安裝虛擬機(jī)的過程請(qǐng)自行搜索查找完成。
??
步驟二:獲取內(nèi)核版本號(hào)
??獲取內(nèi)核版本號(hào)是為了確認(rèn)內(nèi)核版本號(hào)一致。
sudo cat /proc/version
??
步驟三:校準(zhǔn)編譯器版本
??前面獲取了內(nèi)核的編譯器版本是gcc7.3.0,但是本機(jī)是gcc7.5,需要變更版本:
??
步驟四:下載內(nèi)核源碼
sudo cat /proc/versionsudo apt-cache search linux-sourcesudo apt-get install linux-source-4.15.0
??查看到本ubuntu的內(nèi)核版本,然后下載對(duì)應(yīng)的版本:
??
??以上準(zhǔn)備好的內(nèi)核源碼和編譯器則可以開始編譯內(nèi)核。
內(nèi)核編譯
??注意1:ubuntu的/usr/src下有內(nèi)核的頭文件可編譯直接使用。
??注意2:本標(biāo)題章節(jié)所編譯的內(nèi)核然后使用該內(nèi)核編譯的驅(qū)動(dòng)是不可兼容的。
??
步驟一:下載解壓
??
??發(fā)現(xiàn)其實(shí)系統(tǒng)自帶了header頭文件。(PS:-header-?就是頭文件,驅(qū)動(dòng)和某些和內(nèi)核功能關(guān)聯(lián)的東西都要調(diào)用當(dāng)前內(nèi)核版本的對(duì)應(yīng)頭文件才能正確的編譯出來而且可以使用。所以有些發(fā)行版就制作了專用的 header 包來讓需要的程序調(diào)用。這種包只有 header 文件,沒有其他無關(guān)開發(fā)的內(nèi)容。
cd linux-source-4.18.0/sudo tar xvf linux-source-4.18.0.tar.bz2
??
步驟二:內(nèi)核配置
cd linux-source-4.18.0sudo make menuconfig
??
??進(jìn)入了配置:
??
??不做任何配置變動(dòng),退出。
步驟三:直接編譯
make -j8
??
??半小時(shí)左右編譯完成:
??
驅(qū)動(dòng)編譯
??把驅(qū)動(dòng)編譯城模塊,然后加載到內(nèi)核里面。
步驟一:使用前面編寫的驅(qū)動(dòng)和makefile
??
驅(qū)動(dòng)代碼文件
??
#include <linux/init.h>#include <linux/module.h>static int hello_init(void){
? ?// 在內(nèi)核里面無法使用基礎(chǔ)c庫(kù)printf,需要使用內(nèi)核庫(kù)printk
? ?printk(“Hello, I’m hongPangZi\n”);
? ?return 0;}static void hello_exit(void){
? ?printk(“bye-bye!!!\n”);}MODULE_LICENSE(“GPL”);module_init(hello_init);module_exit(hello_exit);
驅(qū)動(dòng)makefile
??
??這里make過不去,發(fā)現(xiàn)這里不能是空格,如下圖,才可以:
??
obj-m += helloworld.o
KDIR:=/usr/src/linux-source-4.18.0/linux-source-4.18.0PWD?=$(shell pwd)all: ? ?make -C $(KDIR) M=$(PWD) modules
步驟二:編譯make
make
??直接在驅(qū)動(dòng)工程目錄編譯:
??
??這里是makefile的m要大寫,修改后可編譯:
??
??應(yīng)該是windows拷貝 過來字符編碼啥的變了(雙引號(hào)),這里更正一下:
??
??
??然后再編譯:
??
??編譯成功
??
步驟三:加載卸載驅(qū)動(dòng)測(cè)試
??將驅(qū)動(dòng)拷貝到開發(fā)板或者目標(biāo)系統(tǒng),然后使用加載指令:
insmod helloworld.ko
??會(huì)打印入口加載的printk輸出。
??
??出現(xiàn)問題可能原因一是內(nèi)核編譯使用的編譯器和模塊使用的編譯器版本不一致。
??這里我們核對(duì)過是一樣的,所以此處暫時(shí)也不知道如何,如下圖:
??
??那么懷疑問題二:編譯模塊時(shí)選擇的Linux頭文件目錄與當(dāng)前運(yùn)行的系統(tǒng)版本不匹配(可能是配置吧,明顯大版本和子版本是一致的)
??所以這里我們重新配置一下makefile,直接引用linux-header如下:
??
??編譯通過:
??
??繼續(xù)加載、查看和卸載測(cè)試:
??
??發(fā)現(xiàn)ubuntu中printk終端無打印的問題,是重定向問題,打入內(nèi)核日志消息了,可以使用dmesg進(jìn)行查看:
??
??至此,會(huì)發(fā)現(xiàn)作為ubuntu來說,自帶的/usr/src下的就是內(nèi)核的頭文件編譯直接使用就可以了,無需編譯內(nèi)核,但是編譯器還是需要的。
??本文章內(nèi)核編譯保留,因?yàn)榫幾g內(nèi)核是一個(gè)準(zhǔn)備條件。