編譯生成新內核
1、實踐原理
Linux模塊是一些能夠做爲獨立程序來編譯的函數和數據類型的集合。之因此提供模塊機制,是由於Linux自己是一個單內核。單內核因爲全部內容都集成在一塊兒,效率很高,但可擴展性和可維護性相對較差,模塊機制可彌補這一缺陷。linux
Linux模塊能夠經過靜態或動態的方法加載到內核空間,靜態加載是指在內核啓動過程當中加載;動態加載是指在內核運行的過程當中隨時加載。shell
一個模塊被加載到內核中時,就成爲內核代碼的一部分。模塊加載入系統時,系統修改內核中的符號表,將新加載的模塊提供的資源和符號添加到內核符號表中,以便模塊間的通訊。函數
2、實踐過程
(一)簡單模塊——姓名post
1.編寫模塊代碼測試
2.編譯模塊this
接下來寫Makefile。spa
三、加載測試卸載模塊指針
sudo insmod lsp.kocode
dmesgblog
(二)進程
1.編寫模塊代碼
模塊構造函數:執行insmod或modprobe指令加載內核模塊時會調用的初始化函數。函數原型必須是module_init(),括號內是函數指針
模塊析構函數:執行rmmod指令卸載模塊時調用的函數。函數原型是module_exit()
模塊許可聲明:函數原型是MODULE_LICENSE(),告訴內核該程序使用的許可證,否則在加載時它會提示該模塊污染內核。通常會寫GPL。
頭文件module.h,必須包含此文件;
頭文件kernel.h,包含經常使用的內核函數;
頭文件init.h包含宏_init和_exit,容許釋放內核佔用的內存。
寫一個簡單的代碼,用來向內核輸出進程信息。
#include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h> #include<linux/sched.h> static struct task_struct *pcurrent; static int __init print_init(void) { printk(KERN_INFO "print current task info\n"); printk("pid\ttgid\tprio\tstate\n"); for_each_process(pcurrent){ printk("%d\t",pcurrent->pid); printk("%d\t",pcurrent->tgid); printk("%d\t",pcurrent->prio); printk("%ld\n",pcurrent->state); } return 0; } static void __exit print_exit(void) { printk(KERN_INFO "Finished\n"); } module_init(print_init); module_exit(print_exit);
2.編譯模塊
接下來寫Makefile。
(其中,all到make的過程當中要使用「回車+Tab」鍵)
obj-m:=proclist.o CURRENT_PATH:=$(shell pwd) LINUX_KERNEL_PATH:= /usr/src/linux-headers-3.13.0-32-generic all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
第一行:本身寫的.c的文件名+」.o」。
第三行的LINUX_KERNEL_PATH後面要寫你本身的內核版本對應的內核源碼包地址.
解釋一下make命令:
make -C $(LINUX_KERNEL_PATH) 指明跳轉到內核源碼目錄下讀取那裏的Makefile
M=$(CURRENT_PATH) 代表返回到當前目錄繼續執行當前的Makefile。
make以後的執行時這樣的:
生成了好多文件:
三、加載模塊
sudo insmod proclist.ko
輸入密碼後便可。此時已經加載了模塊。
四、測試模塊
Dmesg:看內核信息
3、遇到的問題
1. linux的內核版本
uname –r
位數
2.內核位置