lkm(可加载内核模块)
1.lkm编译依托于Linux内核源码
2.完全使用C语言设计规范
3.不能调用任何库文件
查看系统内核版本
uname -r
lkm设计目标
进行内核的二次开发
1.内核的协议栈/系统调用都可以用lkm方式进行开发
2.结合内核的进程管理/文件系统/系统调用/字符驱动/内核网络等机制进行开发
lkm的makefile示例
obj-m += helloworld.o #将当前.o文件编译为lkm
#obj-y 将.o文件编译进kernel
KDIR := /lib/modules/$(shell uname -r)/build
#build文件是一个索引,指向内核源文件
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
#MAKE变量存在于内核源文件,指的是当前系统的交叉编译工具,M指当前目录,使用modules工具将.o文件变为可加载模块
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
lkm的程序示例
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
//入口函数
//内核模块函数都定义为static,防止名字冲突
//__init修饰指的是,将修饰的函数放入到内核代码段(.init.text的section中),方便内核统一管理
static __init int hello_init(void)
{
//printk()函数,由内核实现的打印函数
//printk函数打印的日志使用shell命令dmesg查看
//KERN_DEBUG指的是打印的级别,内核打印分为7个级别
printk(KERN_DEBUG "Hello World!\n");
return 0;
}
//__exit修饰指的是,将修饰函数放入(.exit.text的section中),用于模块的退出
static __exit void hello_exit(void)
{
printk(KERN_DEBUG "See you later.\n");
}
module_init(hello_init);//入口函数修饰
module_exit(hello_exit);//出口函数修饰
MODULE_LICENSE("GPL V2");//模块的许可证声明(必须有,module.h文件中),否则会发出内核被污染 “kernel tainted” 的警告
MODULE_AUTHOR("7c1caf2f50d1");//模块作者
MODULE_DESCRIPTION("Just a module");//模块的描述
lkm模块的加载过程
insmod helloworld.ko #加载模块 .ko文件指内核的.o文件
#调用module_init()修饰的函数
rmmod helloworld.ko #卸载模块
#调用module_exit()修饰的函数
企鹅挑战(eudyptula)
-
第一层:实现lkm模块,完成应用层可以调用,完成lkm的加载和退出
-
第二层:实现特定功能的模块,基于内核各模块的源码
-
第三层:符合内核的结构
-
第四层:融入内核的机制,内核的组件
-
第五层:系统移植
涉及到的Linux命令
dmesg 查看printk打印的日志
dmesg -c 查看并清除当前的日志
lsmod | grep helloworld #查看模块是否存在
modinfo helloworld.ko #查看模块信息
insmod helloworld.ko #加载模块
rmmod helloworld.ko #卸载模块