抓泥鰍

lkmpg

筆記補在下面~

ch1

邱繼寬

表示你的編譯器版本與kernel開發套件所用的編譯器版本不一致,建議安裝對應的版本避免後續開發出問題。

林志芸

Linux 核心模組是一段可以根據需要動態載入和卸載到核心中的程式碼。這些模組可以在不需要重新啟動的情況下加強核心的功能。
如果沒有模組,目前的方法通常是 monolithic kernels (單核),需要將新功能直接整合到核心映像中。這種方法會導致需要更大的核心,並且當需要新功能時,需要重建核心和隨後重新啟動系統。

林本然

A Linux Kernel Module is precisely defined as a code segment capable of dynamic loading and unloading within the kernel as needed.

Linux kernel module 可以在不需要重啟系統的情況下加強 kernel 的功能。在沒有 module 的情況,一般方法都是以 monolithic kernel 為主,直接將功能整合至 kernel image,但這樣在加入新功能時都可能造成子系統需要重啟和 kernel rebuild。

  • Kernel image file : 已編譯完成的核心執行程式,大多與系統啟動較有關聯
  • Kernel rebuild :

在核心模組的 package 裡有提供命令來手動載入:

  • modprobe : 載入指定模組與模組的依賴項
  • depmod : 顯示模組的相依性
  • insmod : 掛載模組
  • lsmod : 檢查有哪些模組已被載入
  • cat /proc/modules : 用來看存了哪些模組
  • lsmod | grep <xxxx> : 列出特定模組的資訊

那有沒有 load 和一般的程式差在哪?

在讓核心模組跑起來之前的準備:

  • Modversioning:若一個核心模組為了某 kernel 編譯,則這個模組在開啟別的 kernel 時不會被 load,除非目前開啟的 kernel 是支援 CONFIG_MODVERSIONS 的,但後面又說要關掉才能使 module 正常運作?求翻譯

ch2

邱繼寬

linux-headers-6.8.0-55-generic

林志芸

林本然

ch3

邱繼寬

Skipping BTF generation for /home/chiu/develop/kernel/hello-1/hello-1.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.8.0-55-generic'

journalct1 ??

林志芸

林本然

ch4

邱繼寬

pr_info() -> print

obj-y vs. obj-m

林志芸

在 Makefile 中加入 PWD := $(CURDIR) 很重要
因為 sudo 出於安全考慮會重置大部分的環境變數,包括 PWD
如果沒有這行程式碼,當執行 sudo make 時,Makefile 可能找不到正確的資料夾

$ lsmod | grep hello

是在尋找名稱中包含 "hello" 的已掛載核心模組。

warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
You are using: gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0

journalctl --since "1 hour ago" | grep "Hello"

掛載模組後,可以輸入以上測試,應該要可以看到 Hello world 1
同理,卸載模組後應該要看到 Goodbye world 1

如果輸入

$ dmesg 

顯示

dmesg: read kernel buffer failed: Operation not permitted

可以試試看

$ sudo sysctl kernel.dmesg_restrict=0

在早期版本的 Linux 核心中,必須使用 init_modulecleanup_module 函式。但現在可以透過使用 module_initmodule_exit 巨集來自定義這些函式的名稱。

__init__exit 巨集

__init 巨集的功能是在模組被寫進核心(built-in)時,使 init function 在完成後被丟棄並釋放其記憶體空間。
他對 loadable modules 沒有影響:

  1. loadable modules 與 built-in drivers 不同,可以在系統運行期間被動態加載和卸載。
  2. built-in drivers 的 init function 只需在系統開機時執行一次;而 loadable modules 在每次被掛載時都需要執行 init function。

__exit 用於模組的 cleanup function。對於built-in drivers,函式會被完全省略(因為永遠不會被卸載);對於 loadable modules 則需要保留以便卸載時執行。

如何設定和傳遞參數給 Linux 核心模組

  1. declare the variables
    首先需要將參數變數宣告為全域變數,使用 module_param 巨集來設定參數。
    module_param 巨集本身有三個參數:
    • 變數名稱
    • 變數類型
    • sysfs 檔案的權限(若為 0 則不會在 sysfs 中建立檔案)
  2. type
  • 整數(有號或無號)
  • 字串
  • 陣列(使用 module_param_array()),必須有一個額外的 pointer to a count variable 作為第三個參數
  1. MODULE_PARM_DESC() 巨集為參數提供描述的文字
  2. 使用 insmod 命令掛載模組時,可以直接在命令後面指定參數值:
    ex.
sudo insmod hello-5.ko mystring="bebop" myintarray=-1

林本然

ch5

邱繼寬

林志芸

模組始於 init_module 函式或 module_init 指定的函式
模組終於 cleanup_module 函式或 module_exit 指定的函式
每個模組必須有 entry 以及 exit function.

核心模組只能使用核心提供的函式,不能使用 standard C library。

One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work — system calls. System calls run in kernel mode on the user’s behalf and are provided by the kernel itself.

printf 函式為例,實際上會調用 write system call。

User Space vs Kernel Space

Unix:

  • highest supervisor mode:所有操作都是允許的
  • lowest user mode

此設計是為了讓核心維持秩序,確保 users 不會任意訪問資源。

Typically, you use a library function in user mode. The library function calls one or more system calls, and these system calls execute on the library function’s behalf, but do so in supervisor mode since they are part of the kernel itself. Once the system call completes its task, it returns and execution gets transferred back to user mode.

Name Space

撰寫核心時,即使是最小的模組也會與整個核心連結,所以 The best way to deal with this is to declare all your variables as static
如果不想將所有變數宣告為靜態,另一個選擇是宣告一個 symbol table 並將其 register 到核心。

Code Space

The kernel has its own space of memory as well. Since a module is code which can be dynamically inserted and removed in the kernel (as opposed to a semi-autonomous object), it shares the kernel’s codespace rather than having its own. Therefore, if your module segfaults, the kernel segfaults.

林本然

ch6

邱繼寬

林志芸

file_operations 結構

包含 pointers to functions defined by the driver that perform various operations on the device.
提供統一的介面讓核心與 driver 之間進行溝通。

struct file_operations fops = {
         .read = device_read,
         .write = device_write,
         .open = device_open,
         .release = device_release
};
  • read: 從裝置讀取資料
  • write: 寫入資料到裝置
  • open: 開啟裝置
  • release: 關閉裝置 (相當於 close)

file 結構

file 是 kernal 層級的結構,絕不會出現在 user space 中
在驅動程式的 file_operations 函式中,file 結構被作為參數傳遞,通過這個結構來維護檔案相關的狀態和操作。

Registering A Device

向 Linux 核心註冊裝置,使其能夠透過檔案系統被存取。為裝置分配一個 major number,作為識別。

  • major number 指示哪個 driver 處理該裝置
  • minor number 僅由 driver 使用,to differentiate which device it is operating on, just in case the driver handles more than one device.

建議使用 cdev interface
步驟一:register a range of device numbers

int register_chrdev_region(dev_t from, unsigned count, const char *name);
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);

The choice between two different functions depends on whether you know the major numbers for your device.

需要動態分配 major number 時使用 alloc_chrdev_region

步驟二:initialize the data structure struct cdev for our char device and associate it with the device numbers.

void cdev_init(struct cdev *cdev, const struct file_operations *fops);
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
  • 先用 cdev_init 初始化 cdev 結構
  • 再用 cdev_add 新增到系統中

舊的 register_chrdev 會占用 major number 下的所有 minor number

林本然

Linux 核心模組運作原理

Linux 核心模組運作原理

3/22 清點

$ sudo insmod kxo.ko
[sudo] password for linmarc: 
insmod: ERROR: could not insert module kxo.ko: Key was rejected by service

3/25 捉其他泥鰍

  • 繼續研讀 list sort
  • 繼續研讀作業三
  • CS:APP 數值系統
  • 了解 ASLR
  • 務必熟悉 select
  • Red_zone

4/2 12:00 checkpoint

  • 研讀作業三
  • CS:APP 數值系統