前言
前面學習了驅動的基礎框架,上一篇編譯了gcc7.3.0,那麼爲了方便很好的熟悉流程,本篇,將使用ubuntu18.04,直接編譯ubuntu18.04的驅動,然後做好本篇文章的相關實戰測試。
本次使用之前rk3568的ubuntu18.04,筆者沒有重新弄了,安裝虛擬機的過程請自行搜索查找完成。
獲取內核版本號是爲了確認內核版本號一致。
sudo cat /proc/version
前面獲取了內核的編譯器版本是gcc7.3.0,但是本機是gcc7.5,需要變更版本:
sudo cat /proc/version
sudo apt-cache search linux-source
sudo apt-get install linux-source-4.15.0
查看到本ubuntu的內核版本,然後下載對應的版本:
以上準備好的內核源碼和編譯器則可以開始編譯內核。
注意1:ubuntu的/usr/src下有內核的頭文件可編譯直接使用。
注意2:本標題章節所編譯的內核然後使用該內核編譯的驅動是不可兼容的。
發現其實系統自帶了header頭文件。(PS:-header- 就是頭文件,驅動和某些和內核功能關聯的東西都要調用當前內核版本的對應頭文件才能正確的編譯出來而且可以使用。所以有些發行版就製作了專用的 header 包來讓需要的程序調用。這種包只有 header 文件,沒有其他無關開發的內容。
cd linux-source-4.18.0/
sudo tar xvf linux-source-4.18.0.tar.bz2
cd linux-source-4.18.0
sudo make menuconfig
進入了配置:
不做任何配置變動,退出。
make -j8
半小時左右編譯完成:
把驅動編譯城模塊,然後加載到內核裏面。
#include <linux/init.h>
#include <linux/module.h>
static int hello_init(void)
{
// 在內核裏面無法使用基礎c庫printf,需要使用內核庫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);
這裏make過不去,發現這裏不能是空格,如下圖,纔可以:
obj-m += helloworld.o
KDIR:=/usr/src/linux-source-4.18.0/linux-source-4.18.0
PWD?=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
make
直接在驅動工程目錄編譯:
這裏是makefile的m要大寫,修改後可編譯:
應該是windows拷貝 過來字符編碼啥的變了(雙引號),這裏更正一下:
然後再編譯:
編譯成功
將驅動拷貝到開發板或者目標系統,然後使用加載指令:
insmod helloworld.ko
會打印入口加載的printk輸出。
出現問題可能原因一是內核編譯使用的編譯器和模塊使用的編譯器版本不一致。
這裏我們覈對過是一樣的,所以此處暫時也不知道如何,如下圖:
那麼懷疑問題二:編譯模塊時選擇的Linux頭文件目錄與當前運行的系統版本不匹配(可能是配置吧,明顯大版本和子版本是一致的)
所以這裏我們重新配置一下makefile,直接引用linux-header如下:
編譯通過:
繼續加載、查看和卸載測試:
發現ubuntu中printk終端無打印的問題,是重定向問題,打入內核日誌消息了,可以使用dmesg進行查看:
至此,會發現作爲ubuntu來說,自帶的/usr/src下的就是內核的頭文件編譯直接使用就可以了,無需編譯內核,但是編譯器還是需要的。
本文章內核編譯保留,因爲編譯內核是一個準備條件。