拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

关于内核模块

关于内核模块

目录

  • 前言
  • 如何制作一个模块
  • 模块编译和加载

前言

我们都知道,Linux这种宏内核类型的内核是高度集成的,牵一发而动全身,我们想在上面修修补补,并且调试是非常困难的,因为每次修改都要重新编译内核,非常费时间,而且实际生产中内核中不是所有东西我们都需要,为了节省内存往往需要裁剪,这时人们便引入模块的概念,这里模块就是动态加载模块,可执行文件是.ko类型的文件,使用时加载,不用时卸载,让我们的调试非常方便,而且模块化的思路也让以后维护系统更加方便。

如何制作一个模块

那么我们如何才能制作一个模块文件呢,首先当然是写源文件了。注意了,写在内核里的模块是不能用我们平时的C库的,最基本的也是最常用的是<linux/init.h><linux/kernel.h>
<linux/module.h>其中第一个记录了__init,__exit这样的修饰词,具体是为了让代码第一次编译后就释放,节约内存,第二个有一些内核里面的库函数,如printk,类似printf但是要自己设置打印等级,第三个非常重要,就是记录有关初始化和卸载的函数。
一般一个模块有以下几个部分,头文件,模块出入口函数(也就是初始化init和卸载exit),模块出入口注册,许可证,模块描述和作者信息,除了最后两个其他都是必须的,我们来看一个例子

#include<linux/module.h>#include<linux/init.h>#include<linux/kernel.h>// 入口函数,insmod时执行staticint__inithello_init(void){printk(KERN_INFO"hello: 模块加载成功!\n");return0;}// 出口函数,rmmod时执行staticvoid__exithello_exit(void){printk(KERN_INFO"hello: 模块卸载成功!\n");}// 注册入口、出口module_init(hello_init);module_exit(hello_exit);// 模块信息MODULE_LICENSE("GPL");MODULE_AUTHOR("test");MODULE_DESCRIPTION("A simple linux kernel module demo");

模块编译和加载

有了c代码但是我们的计算机无法识别C语言,所以还需要编译,这时候我们需要使用make工具(环境搭建请参考其他博主文章),这时就需要写Makefile文件,来指导make工作主要有以下几个部分

#手动定义内核位置 KERNEL_DIR = ../../kernel #定义架构类型 ARCH = arm64 #交叉编译工具前缀 CROSS_COMPILE = aarch64-linux-gnu- #变量导出 export ARCH CROSS_COMPILE #将.o加载为.ko obj-m := hello.o #all是默认目标,即make默认执行项,调用内核编译系统编译模块 all: $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules #第二个目标,make clean触发,删除所有中间文件 clean: $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean

有了这个makefile,我们就可以make来编译了,后面我们拿着.ko文件,需要insmod挂载模块和rmmod卸载模块

sudoinsmod helloworld.kodmesg-C#清空日志sudormmod helloworld.kodmesg#通过观察日志来观察模块情况#注意,这两个命令都需要管理员权限才能运行,即sudo下运行

这样就可以根据日志信息调试了,后续如果确认无误还可以把模块写进内核镜像或者设置开机自启动都可以,这个需要读者自行探索啦。

返回列表