编写函数实现员工信息录入和输出_编写我的第一个Linux 内核模块“hello_module”...
生活随笔
收集整理的這篇文章主要介紹了
编写函数实现员工信息录入和输出_编写我的第一个Linux 内核模块“hello_module”...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:
Linux 內 核 模 塊 全 稱 為 “ 動 態 可 加 載 內 核 模 塊 (Loadable Kernel Module,LKM)”,是系統內核向外部提供的功能插口。作為宏內核結構,Linux 內核具有效率高的特點,但也有可擴展性和可維護性相對較差的不足,Linux 提供模塊機制正是彌補這一缺陷。
模塊是具有獨立功能的程序,它可以被單獨編譯,但不能獨立運行。模塊在運行時被鏈接到內核作為內核的一部分在內核空間運行,這與運行在用戶控件的進程是不同的。模塊通常有一組函數和數據結構組成,用來實現某種文件系統、驅動程序或其它內核上層功能。
本文將介紹如何編寫一個簡單的內核模塊以及如何傳遞參數給此模塊。編寫模塊程序
(1) #include <linux/module.h>:必須。module.h 頭文件包含了對模塊的結構定義以及模塊的版本控制,任何模塊程序的編寫都要包含這個頭文件;
(2) #include <linux/kernel.h>:kernel.h 包含了常用的內核函數,如以上程序中的 printk()函數;
(3) #include <linux/init.h>:必須。init.h 包含了 module_init()和 module_exit()函數的聲明;
(4) module_init():必須。模塊加載函數,加載模塊式該函數自動執行,進行初始化操作;
(5) module_exit():必須。模塊卸載函數,卸載模塊時函數自動執行,進行清理操作; (6) MODULE_LICENSE():表示模塊代碼接受的軟件許可協議。Linux 內核是使用 GPL V2 的開源項目,其要求所有使用和修改了 Linux 內核代碼的個人或組織都有義務把修改后的源代碼公開,這是一個強制的開源協議,所以一般編寫驅動代碼都需要顯示的聲明和遵循本協議,否則內核 UI 發出被污染的警告;
(7) MODULE_AUTHOR():描述模塊的作者信息;
(8) MODULE_DESCRIPTION():簡單描述模塊的用途、功能介紹等;
(9) MODULE_ALIAS():為用戶控件提供的別名;
(10) printk():內核輸出函數,默認打印系統文件 " /var/log/kern.log"的內容。編譯內核模塊
(1) obj-m := <模塊名>.o:定義要生成的模塊名稱
(2) KERNELBUILD := /lib/modules/$(shell uname -r)/build : KERNELBUILD 為自定義名稱,用于指向正在運行 Linux 的內核編譯目錄,其中“uname -r”標識顯示對應的內核版本;
(3) CURRENT_PATH := $(shell pwd):CURRENT_PATH 為自定義名稱,用于指向當前當前目錄;
(4) all:編譯執行的動作
(5) clean:zhixing make clean 需要的動作。“make clean”用于清除上次的 make 命令所產生的 object 文件(后綴為“.o”的文件)及可執行文件。編譯 檢查編譯模塊 插入模塊 查看輸出
因 本 演示 中 prink()采 用 默認 輸出 等級 ,可 通 過“ dmesg” 或“ tail /var/log/kern.log”命令查看輸出結果。 卸載模塊
卸載模塊,可通過“rmmod 模塊名”實現,通 過“ tail /var/log/kern.log”命令查看輸出結果。
Linux 內 核 模 塊 全 稱 為 “ 動 態 可 加 載 內 核 模 塊 (Loadable Kernel Module,LKM)”,是系統內核向外部提供的功能插口。作為宏內核結構,Linux 內核具有效率高的特點,但也有可擴展性和可維護性相對較差的不足,Linux 提供模塊機制正是彌補這一缺陷。
模塊是具有獨立功能的程序,它可以被單獨編譯,但不能獨立運行。模塊在運行時被鏈接到內核作為內核的一部分在內核空間運行,這與運行在用戶控件的進程是不同的。模塊通常有一組函數和數據結構組成,用來實現某種文件系統、驅動程序或其它內核上層功能。
本文將介紹如何編寫一個簡單的內核模塊以及如何傳遞參數給此模塊。
一、 編寫一個簡單的內核模塊
編寫如下簡單代碼,本示例中代碼文件命名“hello_module.c”。
//hello_module.c#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>?static int __init hello_init(void){printk("This is hello_module, welcome to Linux kernel n");return 0;}?static void __exit hello_exit(void){printk("see you next time!n");}?module_init(hello_init);module_exit(hello_exit);?MODULE_LICENSE("GPL");MODULE_AUTHOR("Mr Q");MODULE_DESCRIPTION("hello kernel module");MODULE_ALIAS("hello");以上代碼解釋如下:(1) #include <linux/module.h>:必須。module.h 頭文件包含了對模塊的結構定義以及模塊的版本控制,任何模塊程序的編寫都要包含這個頭文件;
(2) #include <linux/kernel.h>:kernel.h 包含了常用的內核函數,如以上程序中的 printk()函數;
(3) #include <linux/init.h>:必須。init.h 包含了 module_init()和 module_exit()函數的聲明;
(4) module_init():必須。模塊加載函數,加載模塊式該函數自動執行,進行初始化操作;
(5) module_exit():必須。模塊卸載函數,卸載模塊時函數自動執行,進行清理操作; (6) MODULE_LICENSE():表示模塊代碼接受的軟件許可協議。Linux 內核是使用 GPL V2 的開源項目,其要求所有使用和修改了 Linux 內核代碼的個人或組織都有義務把修改后的源代碼公開,這是一個強制的開源協議,所以一般編寫驅動代碼都需要顯示的聲明和遵循本協議,否則內核 UI 發出被污染的警告;
(7) MODULE_AUTHOR():描述模塊的作者信息;
(8) MODULE_DESCRIPTION():簡單描述模塊的用途、功能介紹等;
(9) MODULE_ALIAS():為用戶控件提供的別名;
(10) printk():內核輸出函數,默認打印系統文件 " /var/log/kern.log"的內容。
編寫 Makefile 文件,文件名必須為“Makefile”
obj-m := hello_module.o?KERNELBUILD := /lib/modules/$(shell uname -r)/buildCURRENT_PATH := $(shell pwd)?all:make -C $(KERNELBUILD) M=$(CURRENT_PATH) modules?clean:make -C $(KERNELBUILD) M=$(CURRENT_PATH) clean以上代碼解釋如下:(1) obj-m := <模塊名>.o:定義要生成的模塊名稱
(2) KERNELBUILD := /lib/modules/$(shell uname -r)/build : KERNELBUILD 為自定義名稱,用于指向正在運行 Linux 的內核編譯目錄,其中“uname -r”標識顯示對應的內核版本;
(3) CURRENT_PATH := $(shell pwd):CURRENT_PATH 為自定義名稱,用于指向當前當前目錄;
(4) all:編譯執行的動作
(5) clean:zhixing make clean 需要的動作。“make clean”用于清除上次的 make 命令所產生的 object 文件(后綴為“.o”的文件)及可執行文件。
將以上兩個文件(hello_module.c 和 Makefile)保存于同一目錄下,將上文中代碼存放在路徑為“/code/hellomodule/”,編譯需在文件保存目錄中進行。
編譯成功后,可看到生成的 hello_module.ko 目標文件
可通過 file 命令檢查編譯的模塊是否正確,可以看到 x86-64 架構的 elf文件,說明編譯成功:
也可通過 modinfo 命令進一步檢查 :
通過 insmod 命令插入模塊,完成插入后可通過 lsmod 命令查看當前模塊是否已經被加載到系統中:
系統加載模塊后,也會在“/sys/module”目錄下新建以模塊名命名的目錄 :
因 本 演示 中 prink()采 用 默認 輸出 等級 ,可 通 過“ dmesg” 或“ tail /var/log/kern.log”命令查看輸出結果。
“ tail /var/log/kern.log”命令查看輸出結果:
卸載模塊,可通過“rmmod 模塊名”實現,通 過“ tail /var/log/kern.log”命令查看輸出結果。
二、 模塊參數
Linux 內核提供一個宏來實現模塊的參數傳遞
#define module_param(name, type, perm) module_param_named(name, name, type, perm)?#define MODULE_PARM_DESC(_parm, desc) _MODULE_INFO(parm, _parm, #_parm ":" desc);module_param()宏由 3 個參數組成,name 表示參數名,type 表示參數類型,perm 表示參數讀寫權限。MODULE_PARM_DESC()宏提供參數的簡單說明,參數類型可為 byte、short、int、long、char、bool 等類型;perm 指定在 sysfs 中相應文件的訪問權限,如設置為 0 則不會出現在 sysfs 文件系統中,設置為 0644 標識 root 用戶可修改本參數。 static int debug = 1;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "enable debugging information");?#define dprintk(args...) if(debug){printk(KERN_DEBUG args);}如上述實際代碼所示(driver/misc/altera-stap1/altera.c),實際定義模塊參數 debug,類型是 int,訪問權限是 0644。參數用途是大概調試信息,實際內核編程中常用此方法進行內核調試。修改上文中的“hello_module.c”文件,改為以下內容:
//hello_module.c#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>?static int debug = 1;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "debugging information");?#define dprintk(args...) if(debug){printk(KERN_DEBUG args);}static int myparm = 10;module_param(myparm, int, 0644);MODULE_PARM_DESC(myparm, "kernel module parameter experiment.");??static int __init parm_init(void){dprintk("my linux kernel module init.n");dprintk("module parameter = %dn", myparm);?return 0;}?static void __exit parm_exit(void){printk("see you next time!n");}?module_init(parm_init);module_exit(parm_exit);?MODULE_LICENSE("GPL");MODULE_AUTHOR("Mr Q");MODULE_DESCRIPTION("kernel module paramter experiment");MODULE_ALIAS("myparm");make編譯,裝載模塊,并查看輸出:
通過查看日志信息,可發現輸出以上程序中 參數 的默認值。卸載模塊,賦值重新加載模塊,修改參數 myparm 值為 116:
insmod parm_module.ko myparm=116 通過查看日志信息,可發現 參數 值已經改變。更多內容看看我博客,知乎上格式有點亂了
編寫我的第一個Linux內核模塊“hello_module”_夕源的博客-CSDN博客?blog.csdn.net總結
以上是生活随笔為你收集整理的编写函数实现员工信息录入和输出_编写我的第一个Linux 内核模块“hello_module”...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的集合类型_Python中
- 下一篇: linux 其他常用命令