Linux内核模块的插入和删除

陈莉君老师Linux内核分析与应用课程,一个helloworld内核模块的插入和删除。

目录

编写helloworld.c

一个内核模块大致架构:

编写Makefile

插入模块指令:

删除模块:


编写helloworld.c

代码如下:

#include<unistd.h>//主要对一些系统调用的封装

#include<linux/module.h>//支持内核的模块机制

static int __init lkm_init(void)//__init修饰符,告诉程序只进行初始化,初始化之后释放内存
{
    printk("Hello World\n");//内核模块编写时不能使用printf,使用对应的printk,两者接口完全一样。                
                            //printk支持消息打印的级别,一般支持八个级别。
    return 0;
}

static void __exit lkm_evit(void)
{
    printk("Goodbye");
}

module_init(lkm_init);//模块的入口函数
module_exit(lkm_exit);//模块的出口函数

MODULE_LICENSE("GPL");

一个内核模块大致架构:

首先包含module.h头文件支持内核的模块机制;

接下来编写入口函数和出口;

引导内核入口点,出口点,和许可证的声明。 

编写Makefile

代码如下:

obj-m:=helloworld.o
#使用目标文件建立一个模块,最终生成模块就是helloworld.ko

CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
#当前的内核版本
LINUX_KERNEL_PATH:=/usr/src/kernels/$(LINUX_KERNEL)
#指定内核路径
#为了使makefile文件具有较强的移植性,定义两个路径和一个内核版本


all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
#前面用tab而不是空格
#指定内核路径,编译后的文件放在当前目录,最后加上modules表示我们编译的是内核模块

clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

保存文件名为大写的Makefile。

此处需要安装内核头文件,当前使用的linux系统为CentOS 7。

1.首先使用 uname -r 命令查看当前正在运行的内核版本号,例如:

[root@localhost ~]# uname -r
3.10.0-1160.el7.x86_64

2.然后以此版本号为参数执行以下指令来安装相应的内核头文件:

sudo yum install kernel-devel-$(uname -r)

执行该命令会自动下载并安装与当前正在运行的内核版本相对应的内核头文件。

[root@localhost ~]# sudo yum install kernel-devel-3.10.0-1160.el7.x86_64
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.bupt.edu.cn
 * updates: mirrors.aliyun.com
软件包 kernel-devel-3.10.0-1160.el7.x86_64 已安装并且是最新版本
无须任何处理

安装完成后,你可以在 /usr/src/kernels/ 目录下找到所需的内核源代码和头文件。注意,由于 CentOS 7 中可能存在多个内核版本,因此你需要确保安装了与你当前正在运行的内核版本相对应的内核头文件。

此时使用make指令报错:

[root@localhost module]# make
make -C /usr/src/kernels/3.10.0-1160.el7.x86_64 M=/usr/module modules
make[1]: 进入目录“/usr/src/kernels/3.10.0-1160.el7.x86_64”
  CC [M]  /usr/module/helloworld.o
/usr/module/helloworld.c:1:19: 致命错误:unistd.h:没有那个文件或目录
 #include<unistd.h>
                   ^
编译中断。
make[2]: *** [/usr/module/helloworld.o] 错误 1
make[1]: *** [_module_/usr/module] 错误 2
make[1]: 离开目录“/usr/src/kernels/3.10.0-1160.el7.x86_64”
make: *** [all] 错误 2

在内核编译中不能使用<unstd.h>头文件,需要更改头文件。

修改后的helloworld.c文件:

#include<linux/init.h>//包含了__init宏和__exit宏
#include<linux/kernel.h>//包含了我们常用的内核函数
#include<linux/module.h>

static int __init lkm_init(void)
{
    printk("Hello World\n");
    return 0;
}

static void __exit lkm_evit(void)
{
    printk("Goodbye");
}

module_init(lkm_init);
module_exit(lkm_exit);

MODULE_LICENSE("GPL");

以上头文件在路径:/usr/src/kernels/3.10.0-1160.el7.x86_64/include/linux/可以找到。

重新make后生成.ko文件。


[root@localhost module]# make
make -C /usr/src/kernels/3.10.0-1160.el7.x86_64 M=/usr/module modules
make[1]: 进入目录“/usr/src/kernels/3.10.0-1160.el7.x86_64”
  CC [M]  /usr/module/helloworld.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /usr/module/helloworld.mod.o
  LD [M]  /usr/module/helloworld.ko
make[1]: 离开目录“/usr/src/kernels/3.10.0-1160.el7.x86_64”

此时终端中未打印helloworld。

此时我们与终端打交道的方式不再通过终端,而是通过proc目录下,它可以用于访问一些有关于内核的状态,进程的信息。

/proc/meminfo 这个文件中保存了一些物理内存和交换空间的一些信息。

/proc/kmsg 文件中包含了所有日志信息,各种级别的日志信息都在这里。

使用指令 dmesg 查看所有的日志信息。

插入模块指令:

[root@localhost module]# sudo insmod helloworld.ko

需要使用超级用户权限。

指令 lsmod查看当前系统中的模块。

[root@localhost module]# lsmod
Module                  Size  Used by
helloworld             12423  0
tcp_lp                 12663  0
nls_utf8               12557  1
isofs                  39844  1
xt_CHECKSUM            12549  1
ipt_MASQUERADE         12678  3
nf_nat_masquerade_ipv4    13463  1 ipt_MASQUERADE
tun                    36164  1
devlink                60067  0

此时可以看到我们的helloworld模块已经插入了。

再使用dmesg打印日志,就可以看到输出了。

[16565.493291] helloworld: loading out-of-tree module taints kernel.
[16565.493375] helloworld: module verification failed: signature and/or required key missing - tainting kernel
[16565.508772] Hello World

删除模块:

[root@localhost module]# sudo rmmod helloworld

只需要模块名称不需要后缀了。

查看模块没有了。

[root@localhost module]# lsmod
Module                  Size  Used by
tcp_lp                 12663  0
nls_utf8               12557  1
isofs                  39844  1
xt_CHECKSUM            12549  1
ipt_MASQUERADE         12678  3
nf_nat_masquerade_ipv4    13463  1 ipt_MASQUERADE
tun                    36164  1
devlink                60067  0
ip6t_rpfilter          12595  1
ip6t_REJECT            12625  2

再次打印日志。

[16565.508772] Hello World
[17063.649270] Hello World
[16948.283659] Goodbye/n
[17083.085464] Goodbye/n

以上是一个简单的系统模块的插入和删除。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值