2021 LDD3 第2章
===
contribute by `Liao712148`
###### tags: `Linux Device Drivers`, `Linux `
### 遇到的問題
**ERROR: could not insert module hello.ko: Operation not permitted**
解決辦法:
根據
[insmod: ERROR: could not insert module HelloWorld.ko: Operation not permitted](https://stackoverflow.com/questions/58546126/insmod-error-could-not-insert-module-helloworld-ko-operation-not-permitted)
會使用到
[Why do I get “Required key not available” when install 3rd party kernel modules or after a kernel upgrade?](https://askubuntu.com/questions/762254/why-do-i-get-required-key-not-available-when-install-3rd-party-kernel-modules)
根據
>sudo apt install mokutil
sudo mokutil --disable-validation
之後reboot
---
Makefile 是一種腳本,用來生成模組,
## Makefile
```cpp=
# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifneq ($(KERNELRELEASE),)
# call from kernel build system
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.mod modules.order *.symvers *.dwo *.mod.dwo
```
* 第8行:我們寫的Makefile第一次被執行,此時KERNELRELEASE還沒被定義,因此條件不成立。執行else的內容。
* 第15行:因為`?=`表示如果左邊的變數上未定義,就將右邊賦值給左邊。否則維持原來的值。而`/lib/modules/$(shell uname -r)/build`是核心原碼樹的頂層目錄。,會有一個Makefile幫助我們完成模組。
* 第16行:PWD變數紀錄當的Makefile所在的位子。
* 第18,19行:一開始會切換目錄到`-C`選項所指的目錄(核心原碼樹的頂層目錄),在該處找出核心原碼樹頂層目錄的Makefile。而`M=`選項會使得該Makefile回到模組的原始程式目錄,然後才開始建構第18行所定義的`modules`目標,此目標代表`obj-m`變數所列的模組,也就是`hello.o`。執行第19行時,會造成我們所寫的Makefile又再被執行了一次,此次條件成立,因此會執行第11行。
* 第11行:它宣稱有一個模組要從目的碼`hello.o`建構出來,所產生的模組檔是`hello.ko`。與傳統的Makefile不同,使用了GNU make的擴充語法,樣讓這個Makefile有作用,必須從核心建構系統來調用它 ==> ==利用核心的Makefile來產生模組==。
* 第25行:清除檔案。
```cpp=
#include <linux/init.h>//定義了模組所需的許多函式與變數
#include <linux/module.h>//模組的初始函式與清理函式
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void) {
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void) {
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
```
* 第1,2行:定義於`/usr/src/linux-headers-5.11.0-27-generic/include/linux`。
* 第3行:用來讓kernel知道此模組遵守自由授權條款。
* 第11行:在模組載入kernel時會執行module_init巨集中的函式。也就是helo_init。初始函式是向核心註冊模組所提供新功能(可能是整個驅動程式,或是可供應用程式存取的軟體抽象層)。可以將此函式改成`static int __int hello_init()`當中的`__init`讓核心可以知道該函式==只用於初始期間==。
* 第12行:在模組卸載時會執行module_exit巨集中的函式。也就是helo_exit。清理函式負責在模組被卸載之前,註銷曾這冊的軟體介面,並將資源還給系統。以將此函式改成`static void __exit hello_exit()`當中的`__exit`讓核心可以知道該函式==只用於卸載期間==。
* 第5行:使用的是`printk`而不是`printf`,因為`printf`屬於libc,==模組不能與一般函式庫連結,只能與核心連結==,因此要使用定義於linux核心內的`printk`,可供模組使用。而當中的`KERN_ALERT`代表訊息的優先度,我們刻意指定一個高的優先度,因為預設的優先度不一定會使得訊息出現在你看得到的地方。
---
```cpp=
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>//只要引入sched.h就可以將current當成當時執行的process。
#include <linux/moduleparam.h>
MODULE_LICENSE("Dual BDE/GPL");
static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
static int hello_init(void) {
printk(KERN_ALERT "Hello world\n");
printk(KERN_ALERT "The init process is \"%s\" (pid %i)\n", current->comm, current->pid);
int i;
for(i = 0; i < howmany; i++) {
printk(KERN_ALERT "%s %d times\n", whom, howmany);
}
return 0;
}
static void hello_exit(void) {
printk(KERN_ALERT "Goodbye, curel world\n");
printk(KERN_ALERT "The exit process is \"%s\" (pid %i)\n", current->comm, current->pid);
}
module_init(hello_init);
module_exit(hello_exit);
```
* 第3, 11, 21行:核心的大部份動作,都是在代替當時正在執行的process執行遠本無法在user-space完成的工作。透過定義於`<asm/current.h>`的全局變數`current`,current永遠指向當時正在執行的process。透過current,核心程式可以取得當時正在執行的狀態資訊。
* 第6,7,8,9行:在`insmod`時改變系統的參數,模組本身要先以`module_param`巨集來宣告參數。
>`#` insmod hello.ko howmany=10 whom="Mom"
==所有的模組參數都必須有預設值==,`module_param()`的最後一欄是權限值,決定模組參數在sysfs裡的對應項目的存取權限。
### 參考資料
[Makefile 語法和示範](https://hackmd.io/@sysprog/SySTMXPvl)
[編譯內核模塊的的Makefile的講解](https://www.twblogs.net/a/5b81bc442b71772165ae0321)
[驅動模組Makefile解析](https://www.itread01.com/p/1377069.html)