1. 程式人生 > >【迅為iTop4412學習筆記】1. 最簡linux驅動

【迅為iTop4412學習筆記】1. 最簡linux驅動

本節目標

  1. 載入、解除安裝驅動的時候列印一段話(總不是HelloWorld…之類的)
  2. 簡單的Makefile編譯

一、標頭檔案

// 載入,解除安裝的初始化需要包含此標頭檔案
#include <linux/init.h>
// 模組相關的庫函式需要包含此標頭檔案
#include <linux/module.h>

我目前發現的是這些標頭檔案源自以下位置,要找庫函式可以自己找目錄下的標頭檔案看,瞭解下就行:

  1. 迅為原始碼相對連結:Android4.0/iTop4412_Kernel_3.0/include 下。
  2. 本機ubuntu絕對連結:/usr/src/linux-headers-3.5.0-23-generic/include 下。中間的“3.5.0-23-generic”核心版本號要控制檯shell用 uname -r 檢視,用返回的值去替換,你 ls /usr/src 其實就可以看到本機所有的核心版本號的資料夾。

二、GPL協議

// 宣告GPL許可證,總之免費使用,但是要開源
MODULE_LICENSE("Dual BSD/GPL");
// 這裡是作者
MODULE_AUTHOR("MrYang");

這些內容是必要的,否則無法編譯通過,要遵守開源的規則!

四、模組的init和exit

// 函式名很清楚了...
module_init();
module_exit();

有沒有好奇為什麼是四而不是三?
兩者括號內參數為你init,exit需要呼叫的函式名,所以你需要先定義這些函式。
所以第三步應該先定義這些函式。

三、定義init和exit需要呼叫的函式

// 用於init時呼叫的函式
static int hello_init(void)
{
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	return 0;
}
// 用於exit時呼叫的函式
static void hello_exit
(void) { printk(KERN_EMERG "HELLO WORLD exit!\n"); }
  1. 首先注意到輸出函式並非C語言常用的printf,而是printk,k應該是指kernel吧…輸出內容前的KERN_EMERG是指控制核心log輸出級別,還有很多就不介紹了,百度一搜就有了(其實我也沒了解哈哈)
  2. hello_init和hello_exit是我們自定義的函式名,你也可以改成別的,然後把函式名分別當作第四步模組的引數就行了

五、貼出模組內的所有程式(mini_linux_module.c)

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("MrYang");

static int hello_init(void)
{
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_EMERG "HELLO WORLD exit!\n");	
}

module_init(hello_init);
module_exit(hello_exit);

這裡先挖坑以後修改補充

六、寫一個Makefile對程式進行自動化編譯

#!/bin/bash
#通知編譯器我們要編譯模組的哪些原始碼
#這裡是編譯itop4412_hello.c這個檔案編譯成中間檔案itop4412_hello.o
obj-m += mini_linux_module.o 

#原始碼目錄變數,這裡使用者需要根據實際情況選擇路徑
#作者是將Linux的原始碼拷貝到目錄/home/topeet/android4.0下並解壓的
KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

#當前目錄變數
PWD ?= $(shell pwd)

#make命名預設尋找第一個目標
#make -C就是指呼叫執行的路徑
#$(KDIR)Linux原始碼目錄,作者這裡指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
#$(PWD)當前目錄變數
#modules要執行的操作
all:
	make -C $(KDIR) M=$(PWD) modules
		
#make clean執行的操作是刪除字尾為o的檔案
clean:
	rm -rf *.o

Makefile顯然不是我寫的,這其實可以當作一個模板,因為東西很少,所以看起來比較直觀,名字不對改名字,程式包含標頭檔案的所在路徑不對就改路徑。迅為的說法是不要過分的去學習Makefile檔案,會改就完事了,本懶人贊同!

七、編譯,載入、檢視、解除安裝等等…

最後倆檔案 mini_linux_module.c 和 Makefile 放在一起編譯,也就是控制檯輸入

make

生成mini_linux_module.ko檔案就是最後驅動了。

我們把生成的驅動放到U盤然後插入板子
輸入命令掛載U盤到/mnt/disk目錄

mount /dev/sda1 /mnt/disk

然後我們進入/mnt/disk目錄就可以載入、解除安裝驅動了!
載入驅動:

insmod mini_linux_module.ko

檢視驅動:

lsmod

解除安裝驅動:

rmmod mini_linux_module

注意 解除安裝不帶.ko

解除安裝的時候我出現了點小問題,發現解除安裝失敗,後來百度搜的方法是:

  1. 控制檯uname -r 檢視核心版本,返回:3.0.15
  2. 新建資料夾 mkdir /lib/modules/3.0.15,再解除安裝 就OK了
    補充1:原來迅為的pdf裡有寫,所以說還是要認真看迅為給的資料…
    補充2:沒有板子在虛擬機器內也可以完成本節,但printk無輸出,可以先安裝sudo apt install busybox-syslogd,再用命令sudo cat /proc/kmsg,就可以完整顯示核心訊息了,若要後臺命令後面就加個&。

寫在最後

最簡單的驅動就此完成了,以後有什麼修改再回來看,再回來改。