contributed by < HotMercury
>
注意細節!要更新 HackMD 筆記的標題。
Linux 核心模組運作原理
ubuntu linux 預設開啟 EFI_SECURE_BOOT_SIG_ENFORCE
當使用第三方 kernel module 時,所以有幾種方法可以解決。
這裡嘗試理解 UEFI Secure Boot
What is UEFI Secure Boot?
UEFI is unified extensiblt firmware interface 更多細節可以參考 man page,UEFI secure boot,用來避免在 boot process 時載入惡意程式,大部分的 x86 hardware 都有 microsoft key 但我們還是可以透過 disable or 更改 sign key,所以 SB 並不是微軟帝國為了防止其他 OS 的手段。
改進漢語表達。
kernel module 前置作業
Install the header files for the kernel
The Linux Kernel Module Programming Guide 提供安裝的 example,我認為是可以改成以下方式比較容易跟著做,我想嘗試貢獻。
They are defined within include/linux/module.h
This exists for several reasons
- So modinfo can show license info for users wanting to vet their setup is free
- So the community can ignore bug reports including proprietary modules
- So vendors can do likewise based on their own policies
如果直接在 make file 裡面使用 PWD := &(CURDIR)
可能會有錯誤
In the sudoers security policy, env_reset is enabled by default, which restricts environment variables.
掛載
hello.ko
make check
後會有以下的 warning,跟據 ISO C90 forbids variable length array 使用 dynamic allocate,因為在 kernel 中所以使用 kmalloc
kernel module 會用到的 macro,而這些 macro 是怎麼讓 kernel 知道的,以及 insmod 對應的 linux 內部操作有什麼關西?
接下來的 code 接來自 linux v6.8 且假設我的 code 是 MODULE_AUTHOR("Jay")
include/linux/module.h
展開成 MODULE_INFO(author, "Jay")
展開成 __MODULE_INFO(author, author, "jay")
為什麼需要傳入兩個 tag 是為了統一界面?
你做實驗,看能否通過編譯。
__section
: GCC extension determine the storage location of the object tagged with it.
__stringify
: #define __stringify_1(x...) #x
include/linux/moduleparam.h
探討 __UNIQUE_ID(author)
,所以展開會變成 __UNIQUE_ID_author0
__COUNTER__
根據 The C Preprocessor This macro expands to sequential integral values starting from 0
Care must be taken to ensure that
__COUNTER__
is not expanded prior to inclusion of precompiled headers which use it. Otherwise, the precompiled headers will not be used
所以最後的展開為以下
接下來透過 objdump 觀察
objdump - display information from object files
閱讀《Linux Device Driver 3/e》 Initialization and Shutdown
initialization functions 通常會以 static 的方式,因為通常只被用來註冊使用。
The module loader drops the initialization function
after the module is loaded, making its memory available for other uses.
避免過多的中英語詞彙交錯
建構 Linux 核心模組所用到的巨集 kernel module 的 macro 會增加 specail section ?? 因此可以找到對應的 module initialization function.
至於 module function 會被如何呼叫
Modules can register many different types of facilities, including different kinds of devices, filesystems, cryptographic transforms, and more. For each facility, there is a specific kernel function that accomplishes this registration. The arguments passed to the kernel registration functions are usually pointers to data structures describing the new facility and the name of the facility being registered. The data structure usually contains point
閱讀 workqueue
非同步的執行上下文通常會使用 workqueue API,所以可以想像成一個代工廠,將任務交給工廠,如果沒有任務,工人就可以去放假。
原本設計的 multi-thread 是一個 core 一個 thread,而 single thread 則是共用一個,每個 workqueue 會維護一個 work pool,以上不管是 MT or ST 都沒有足夠好的 concurrency,因此接下來要探討 Concurrency Managed Workqueue
這裡提到 default 32k PID 是什麼意思
The kernel grew a lot of MT wq users over the years and with the number of CPU cores continuously rising, some systems saturated the default 32k PID space just booting up.
Concurrency Managed Workqueue
goal
Design
要使用 wq 時會先初始化 work item,指向 function 並放入 work queue。
接下來搭配 simrupt.c 來理解 wq API
是一個 kernel module device driver 用來做 deffered work
simrupt_init
接著透過 alloc_chrdev_region
註冊 Character devices,cdev_init
初始化 struct cdev 以及對應的 operations。
alloc_workqueue
alloc a wq@name : wq 的名字
@flags : 可以設定 wq 的模式