Linux内核采用宏内核架构,即操作系统的大部分功能都在内核中实现,比如进程管理、内存管理、进程调度、设备管理等,并且都在特权模式下(内核空间)运行。而与之相反的另一种流行的架构是微内核架构,它把操作系统最基本的功能放入内核中,而其他大部分的功能(如设备驱动等)都放到非特权模式下,这种架构有天生优越的动态扩展性。

内核模块全称Loadable Kernel Module(LKM)。在内核运行时加载一组目标代码来实现某个特定的功能,这样在实际使用Linux的过程中可以不需要重新编译内核代码来实现动态扩展。

Linux内核通过内核模块来实现动态添加和删除某个功能。

简单的模块代码

#include <linux/init.h>
#include <linux/module.h>static int __init my_test_init(void)
{printk("my first kernel module init\n");return 0;
}static void __exit my_test_exit(void)
{printk("goodbye\n");
}module_init(my_test_init);
module_exit(my_test_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("rlk");
MODULE_DESCRIPTION("my test kernel module");
MODULE_ALIAS("mytest");

第1行和第2行包含了两个Linux内核的头文件,其中<inux/init.h>头文件对应的是内核源代码的include/inux/init.h文件,在这个头文件中包含了第14行和第15行中的module_inito() 和module_exit() 函数的声明。<linux/module.h>头文件对应的是内核源代码的include/inux/module.h文件,包含了第18-21行的MODULE_AUTHOR()这些宏的声明。

第15行的module init()告诉内核这是该模块的入口。

第16行的module_exit()宏告诉内核这个模块的退出函数是my_test_exit()。

第4-8行是该内核模块初始化函数,这个函数在内核模块被加载时运行,可以使用insmod命令来加载一个内核模块。

第10-13行是该内核模块的退出函数,该函数在模块被卸载时自动运行,可以使用rmmod命令卸载一个内核模块。

第18-21行,MODULE_LICENSE()表示这个模块代码接受的软件许可协议。MODULE_AUTHOR()用来描述该模块的作者信息,可以包括作者的姓名和邮箱等。MODULE_DESCRIPTION()用来简单描述该模块的用途或者功能介绍。MODULE_ALIAS()为用户空间提供一个合适的别名。

下面我们来看编译这个内核模块的Makefile文件。

BASEINCLUDE ?= /lib/modules/`uname -r`/buildmytest-objs := my_test.o
obj-m  := mytest.oall : $(MAKE) -C $(BASEINCLUDE) M=$(PWD) modules;clean:$(MAKE) -C $(BASEINCLUDE) M=$(PWD) clean;rm -f *.ko;

第1行的BASEINCLUDE指向正在运行Linux的内核编译目录,通过"uname -r"命令可以找到对应的内核版本。

第3行表示该内核模块需要哪些目标文件,格式是:
<模块名>-objs := <目标文件>.o

第4行表示要生成的模块。注意,模块名字不能和目标文件名相同。格式是:
obj-m := <模块名>.o

第6-7行表示要编译执行的动作。
这里的$(MAKE)就相当于make,-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。

第9-11行表示执行make clean需要的动作。

编译模块

在终端中输入make命令执行编译,编译完成之后会生成mytest.ko文件。

安装模块

接下来就可以安装我们的模块:

你会发现没有输出,别着急,因为例子中的输出函数printk()的默认输出等级,可以使用dmesg命令查看内核的打印信息。


另外,你可以通过1smod命令查看当前mytest模块是否已经被加载到系统中,它会显示模块之间的依赖关系。

加载模块之后,系统会在/sys/modules目录下新建一个目录,比如对于mytest模块会建一个名为mytest的目录。

卸载模块

可以通过rmmod卸载模块

模块参数

内核模块作为一个可扩展的动态模块,为Linux内核提供了灵活性。但是有时我们需要根据不同的应用场景给内核模块传递不同的参数。

1. 参数声明及初始化

如果需要向内核模块传递参数,该参数必须事先在模块代码中声明及初始化:

module_param(name,type,perm);
MODULE_PARM_DESC(parm,desc);

module_param()宏由3个参数组成,name表示参数名,type表示参数类型,perm表示参数的读写等权限。参数类型可以是byte,short,ushort,int,uint,long,ulong,char和bool等类型。perm指定在sysfs中相应文件的访问权限,如设置为0表示不会出现在sysfs文件系统中;如设置成S_IRUGO(0444)可以被所有人读取,但是不能修改;如设置成S_IRUGO|S_IWUSR(0644),说明可以让root权限的用户修改这个参数。

MODULE_PARM_DESC()宏为这个参数的简单说明。

例如上面的模块添加参数a,代码如4~6行所示,第11行将该参数打印出来

#include <linux/init.h>
#include <linux/module.h>static int a = 100;
module_param (a, int, 0644);
MODULE_PARM_DESC(a, "test for module parameter");static int __init my_test_init(void)
{printk("my first kernel module init\n");printk("module parameter=%d\n", a);return 0;
}static void __exit my_test_exit(void)
{printk("goodbye\n");
}module_init(my_test_init);
module_exit(my_test_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("rlk");
MODULE_DESCRIPTION("my test kernel module");
MODULE_ALIAS("mytest");

编译和加载上面的模块之后,通过dmesg查看内核登录信息,会发现输出a的值为默认值100。

2. 调用模块参数

当通过"insmod mymodule.ko a=200”命令来加载模块时,可以看到终端dmsg输出为:

3. 查看模块参数

/sys/module/XXXXX/parameters目录下面可以看到模块参数。

符号共享

我们在为一个设备编写驱动程序时,会把驱动按照功能分成好几个内核模块,这些内核模块之间有一些接口函数需要相互调用,这怎么实现呢?Linux内核为我们提供两个宏来解决这个问题。

EXPORT_SYMBOL()
EXPORT_SYMBOL_GPL()

EXPORT_SYMBOL()把函数或者符号对全部内核代码公开,也就是将一个函数以符号的方式导出给内核中的其他模块使用。
其中,EXPORT_SYMBOL_GPL()只能包含GPL许可的模块,内核核心的大部分模块导出来的符号都是使用GPL这种形式的。如果要使用EXPORT_SYMBOL_GPL()导出函数,那么需要显式地通过模块申明为"GPL",如MODULE_LICENSE(“GPL”)。

内核导出的符号表可以通过 cat /proc/kallsyms来查看。

其中,第1列显示的是该符号在内核地址空间的地址;第2列是符号属性,比如T表示该符号在text段中;第3列表示符号的字符串,也就是EXPORT_SYMBOL()导出来的符号;第4列显示哪些内核模块在使用这些符号。

内核模块结构总结

  • 模块加载函数:加载模块时,该函数会被自动执行,通常做一些初始化工作。
  • 模块卸载函数:卸载模块时,该函数也会被自动执行,做一些清理工作。
  • 模块许可声明:内核模块必须声明许可证,否则内核会发出被污染的警告。
  • 模块参数:根据需求来添加,为可选项。
  • 模块作者和描述声明:一般都需要完善这些信息。
  • 模块导出符号:根据需求来添加,为可选项。

《奔跑吧Linux内核(第二版)》第五章笔记相关推荐

  1. 琢石成器――windows环境下32位汇编语言程序设计(第三版)笔记

    琢石成器――windows环境下32位汇编语言程序设计(第三版)笔记 2011年12月20日 基础篇 第1章 背景知识 1 1.1 Win32的软硬件平台 1.1.1 80x86系列处理器简史 1.1 ...

  2. Windows环境下32位汇编语言程序设计(典藏版)(含CD光盘1张)

    Windows环境下32位汇编语言程序设计(典藏版)(含CD光盘1张)(畅销10年,经典再现!) 罗云彬 著 ISBN 978-7-121-20759-4 2013年7月出版 定价:99.00元 75 ...

  3. Windows环境下32位汇编语言程序设计 相关资料

    Windows环境下32位汇编语言程序设计.pdf:https://474b.com/file/15153148-465076702 <Windows环境下32位汇编语言程序设计>随书光盘 ...

  4. Windows环境下32位汇编语言程序设计(典藏版)

    <Windows环境下32位汇编语言程序设计(典藏版) > 基本信息 作者: 罗云彬 出版社:电子工业出版社 ISBN:9787121207594 上架时间:2013-7-8 出版日期:2 ...

  5. windows环境下32位汇编语言程序设计 90盘_Python 0基础详细教程 环境安装01

    Python语言有什么用,首先让大家了解Python语言的基本知识: Python语言是一种解释型,面向对象,动态数据类型的高级程序设计语言,Python语言是数据分析师的首选数据分析语言,通过数据挖 ...

  6. windows环境下32位汇编语言程序设计 90盘_程序设计作业题汇总

    C语言程序的基本单位是函数 程序设计语言经历了"机器语言"-"汇编语言"-"高级语言"的发展过程. 编写C语言代码文件的拓展名为.c/编写C ...

  7. 《Windows环境下32位汇编语言程序设计》 第五章笔记

    WM_COMMAND产生的条件:点击菜单, 点击加速键,点击子窗口按钮,点击工具栏按钮,点击列表框.这些时候都有command消息产生 wParam 高16位通知码,低16位命令ID, lParam ...

  8. Windows环境下32位汇编程序设计C版code--第四章

    采用的编译环境为VC++6.0 (一)第一个窗口函数 FirstWindow.c#include <windows.h> LRESULT CALLBACK ProcWinMain(HWND ...

  9. Windows环境下32位汇编程序设计C版code--第五章(三)

    (三)窗口子控件 #include <windows.h> #include "resource.h" HINSTANCE hInst; TCHAR szBuffer[ ...

  10. Windows环境下32位汇编程序设计C版code--第五章(二)

    (二)图标和光标 #include <windows.h> #include "Resource.h" TCHAR szName[] = TEXT("Icon ...

最新文章

  1. java对象排序_java对象排序(Comparable)详细实例
  2. 修改自动生成get/set方法模板代码
  3. flowable支持的mysql版本_Flowable3-配置
  4. 华为发布基于第二代英特尔®至强®可扩展处理器家族的新一代服务器
  5. Nancy 学习-进阶部分 继续跨平台
  6. JVM优化系列-JVM内存溢出的原因
  7. 非旋Treap——维护数列
  8. YUV、YUV420P(YU12和YV12)、NV12、NV21编码
  9. Android优雅地判断软键盘弹出状态
  10. 【干货】Excel中的换行符,这几种用法你会哪些?
  11. WIN10删除微软拼音输入法,设置默认输入法为英文
  12. cyclone小知识(四)——利用cyclone和PS制作点云剖面图(包括画直角坐标系)
  13. mysql面试题50
  14. 如何利用CustomFont+PS制作字体
  15. LaTeX:pgf usepackage(宏包)的中译
  16. PS作业-Camera Raw滤镜练习
  17. 详解HTML的相对路径写法
  18. gihub上传本地项目简单步骤
  19. Linq to Sql 事务处理
  20. Kubernetes 网络入门

热门文章

  1. 获取impala下所有的数据库建表语句
  2. 宁波专业SEO,如何让网站快速排名?
  3. Matlab 遗传算法解决智能排课算法 一天四节课,上午两节,下午两节,同一门课不能相邻,特殊课程不能相邻(语文和英语,数学和科学),求可行方案?
  4. 如何查询202118山东高考成绩,往年高考成绩怎么查询 查询成绩的方法
  5. Mac环境下生成ssh密钥
  6. AndroidStudio项目组件化maven上传gradle-module aar上传
  7. WEB安全:什么是Cookie,Cookie数据泄漏的危害
  8. wait millis 60010, active 20, maxActive 20 处理 com.alibaba.druid.pool.GetConnectionTimeout
  9. foxmail配置qq邮箱(需要在QQ邮箱设置第三方授权码
  10. 人像摄影的美姿和构图技巧