Linux内核模块基础知识+踩坑经历

一、内核模块基础知识

1. 模块的基础操作

以下操作以C语言经过make编译生成的hello-1.ko模块作为示例

  • lsmod或cat /proc/modules

    显示当前被内核加载的模块

  • modinfo hello-1.ko

    查看内核模块的信息,包括开发人员信息,依赖信息

  • insmod ./hello-1.ko

    将新编译的模块插入到内核中,一次只能接一个

  • rmmod hello-1.ko

    从内核中删除模块

  • dmesg | tail或tail /var/log/messages

    查看printk出的结果,它会写入到系统日志中去。推荐使用dmesg | tail,可能一下就可以了,如果使用tail /var/log/messages报错说没有那个文件,请看本文结尾——二、问题汇总。

2. 内核模块编译

首先,创建一个Makefile文件(注意,命名就是Makefile,没有后缀的普通文件,不可变),然后直接套用一个模板,往里写入:

obj-m += hello-1.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

注意: Makefile文件对格式要求很严,如果复制我的模板过去,all和clean中的内容,本来是缩进(Tab)的,会被解释程多个空格,你可以在vim编辑中发现异常,该部分代码变红了,你可以删除这多个空格,然后按Tab缩进。

其中需要改动的就是,obj-m +=hello-1.o,用于更换编译对象(这里编译的对象是hello-1.c文件,下一张图我的编译对象是lab3^.c),剩下的all和clean中的代码不需要改动。

然后当前目录下就有.c,和没有后缀名的普通文件Makefile了,直接在命令行输入make即可编译。编译之后,可以看到当前目录下,生成了一大堆文件,其中的.ko文件就是模块了(内核2.6引入了一种新的文件命名约定:内核模块现在具有的.ko扩展名代替旧的.o扩展名,方便与传统的目标文件区分)
make编译之后的结果

3. 模块部分书写(C语言)

  • init_module()和cleanup_module()是Linux2.4之前的,之后可以重命名,通过module_init()和module_exit()和module_exit()宏完成的,自由度更高,这些宏,在linux/init.h定义,需要包括头文件

    #include <linux/init.h>
    
  • MODULE_DESCRIPTION(),宏,在linux/module.h中定义

    用于描述模块的功能,MODULE_AUTHOR()声明模块的作者

  • MODULE_AUTHOR(),宏,在linux/module.h中定义

    声明模块的作者

  • MODULE_SUPPORTED_DEVICE(),宏,在linux/module.h中定义

    声明模块的作者

3.1 变量

module_param()宏,定义在linux/moduleparam.h中,变量必须先声明为全局变量,才能作为参数

  • 参数

    变量名称,它在sysfs中对应的文件的类型和权限,总共三个参数

    变量为字符串的情况举例

  static char *mystring = "blash"
  module_param(mystring, charp, 0000);
  • module_param_array()和module_param_string()

    相比于module_param()在第二和第三个参数之间,多了一个地址变量,用于储存在装载模块时,用户初始化变量的个数,也可以忽略计数传递参数NULL

3.2 多文件组合模块

先写两个.c文件,例如,start.c和stop.c文件,然后在Makefile文件中写入

obj-m +=startstop.o
startstop-objs := start.o stop.o

在make之后,会生成startstop.ko模块

二、问题汇总

  • 无法查看/var/log/messages系统日志,提示没有哪个目录

    • vim /etc/rsyslog.d/50-default.conf

      对于Linux命令不太熟悉的同学,也可以使用gedit编辑,权限不够提高权限, sudo gedit /etc/rsyslog.d/50- default.conf,或者切换root用户,su root,输入密码,gedit /etc/rsyslog.d/50-default.conf

    • 将其中以Some “catch-all” log files开头,mail,news.none结尾的部分去掉注释符

    • 重启rsyslog服务,restart rsyslog,如果说找不到这个job,可以重启

    • 然后tail -f /var/log/messages就可以看到系统日志了

  • 编译之后发现如下警告,warning:ISO C90 forbids mixed declaratios and code …
    warning提示信息

    • 在内核模块编程中,应该把变量声明int id1=1,id2=2放在最前面去,即变量的声明应该放在语句之前。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

upupoo577

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值