一起学习Linux内核模块的知识,为编写复杂的设备驱动做好准备

一、Linux内核模块简介

Linux内核的整体架构非常庞大,包含的组件非常多,如果把所有的功能都编译到内核,有导致生成的内核映像越来越大,同时如果我们要修改现有内核的功能,需要重编内核,效率很低

有没有另一种机制可使得内核本身不包含所有功能,而在这些功能需要被使用的时候,其对应的代码才被动态地加载的内核中呢?

Linux提供了这样的机制,就是模块(Module),模块具有这样的特点:

  • 模块本身不被编译到内核映像,从而控制了内核的大小

  • 模块一旦加载,和内核的其他部分完全一样。

二、Linux内核模块组成

一个linux内核模块主要包含以下几个部分。

  • 模块加载函数

  • 模块卸载函数

  • 模块参数(可选)

  • 模块导出符号(可选)

  • 模块作者等信息声明(可选)

2.1 模块加载函数

当通过insmodmodprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的初始化工作。

内核加载函数一般以__init 标识声明,典型的模块加载函数的形式如下所示:

static int __init init_func(void)
{...
}
module_init(init_func);

返回整形值,成功返回0,失败返回错误码,如-ENODEV、ENOMEM(asm-generic/errno-base.h)。

在linux内核中,可以使用request_module加载内核代码,灵活地使用其他模块。

int __request_module(...);
eg:
request_module("module_name");

2.2 模块卸载函数

linux内核卸载模块一般以__exit标识声明,典型的模块卸载函数的形式如下所示:

static void exit_func(void)
{...
}
module_exit(exit_func);

模块卸载函数在模块卸载的时候执行,不返回任何值,且必须使用module_exit函数来指定,我们使用__exit修饰模块卸载函数,可以告诉内核如果相关的模块被直接编译到内核,则exit_func函数会被省略,直接不链接到最后的镜像。

2.3 模块参数

我们可以用"module_param(参数名,参数类型,参数读/写权限)",为模块定义一个参数。例如:

// test_lockup.c
static unsigned int time_secs;
module_param(time_secs, uint, 0600);
MODULE_PARM_DESC(time_secs, "lockup time in seconds, default 0");

在装载内核模块时,用户可以向模块传递参数,形式如下,如果模块内置了,就无法再insmod了。

insmode(或modprobe) 模块名 参数名="参数值",参数名="参数值"

参数类型可以byte、short、ushort、int、uint、long、ulong、charp、bool、invbool。除此之外还可以使用"moudule_param_array"传递参数数组。

2.4 导出符号

Linux的"/proc/kallsyms"文件对应着内核符号表,记录了符号以及符号所在的内存地址。 模块可以使用如下宏导出到内核符号表中,导出的符号可以被其他模块使用。

EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);

2.5 模块声明和描述

linux可以可以声明模块的作用、描述、版本、设备表和别名、许可权限,如:

MODULE_AUTHOR("author");
MODULE_DESCRIPTION("description");
MODULE_VERSION("version");
MODULE_DEVICE_TABLE("device_table");
MODULE_ALIAS("alias");
MODULE_LICENSE("license");

2.6 模块的使用计数

linux2.4内核中,模块自身通过MOD_INC_USE_COUNT、MOD_DES_USE_COUNT来管理自己被使用的计数。

linux2.6内核中,提供了模块计数管理接口:

bool try_module_get(struct module *module); //增加模块使用计数
void module_put(struct module *module);     //减少模块使用计数

三、示例

模拟处理器软件:qemu

内核:linux-6.9.1

编译工具链:CONFIG_COMPILE=x86_64-linux-gnu-

架构:ARM=x86

3.1 foo.c

// foo.c
#include <linux/module.h>
#include <linux/init.h>static int __init foo_init(void)
{printk(KERN_INFO "hello foo\n");return 0;
}static void __exit foo_exit(void)
{printk(KERN_INFO "goodbye foo\n");
}module_init(foo_init);
module_exit(foo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("simon");
MODULE_DESCRIPTION("a simple module example");
MODULE_VERSION("v1.0");
MODULE_ALIAS("simon_char");

3.2 Makefile

这里的示例没有嵌入到内核树中,是可以单独编译的。需要将Makefile和embei_foo.c放到同一个指令,执行make指令即可。

// Makefile
obj-m += foo.oPWD=$(shell pwd)
KERNEL_DIR="/home/simon/share/linux/linux-6.9.1" // 换成自己的内核路径all:make -C $(KERNEL_DIR) M=$(PWD) modules
clean:make -C $(KERNEL_DIR) M=$(PWD) clean

四、总结

本文首先对linux内核模块的特点进行了概述,其模块本身不被编译到内核映像,从*有效地控制内核映像的大小,同时模块一旦加载,和内核的其他部分完全一样

然后对内核的组成进行了讲解,其主要包含内核模块加载函数、卸载函数、模块参数、导出符号、模块声明和描述以及模块的使用计数

最后以一个简单的模块示例,把整个流程跑了一遍,同时对涉及到的命令做了展示。希望大家可以掌握此部分的知识,为编写其他设备驱动做好准备。

一个专注于“嵌入式知识分享”、“DIY嵌入式产品”的技术开发人员,关注我,一起共创嵌入式联盟。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/25691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全的神秘世界】web应用程序安全与风险

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 第一章&#xff1a;web应用程序安全与风险 web攻击基础知识 1、什么是web应用攻击 web攻击的本质&#xff0c;就是通过http协议篡改应用程序&#xff0…

c#自定义ORM框架-实体类扩展属性

步骤一、建立扩展属性类 实体类扩展属性要继承Attribute基类完成 步骤二、创建实体类并引用扩展实体类属性 Attributes属性定义&#xff0c;主要标明表名和主键名字 /// <summary> /// 表名 /// </summary> [AttributeUsage(AttributeTargets.Class)] [System.S…

蓝牙安全入门——两道CTF题目复现

文章目录 蓝牙安全入门题目 low_energy_crypto获取私钥解密 题目 蓝牙钥匙的春天配对过程配对方法密钥分发数据加密安全漏洞和保护实际应用实际应用 蓝牙安全入门 &#x1f680;&#x1f680;最近一直对车联网比较感兴趣&#xff0c;但是面试官说我有些技术栈缺失&#xff0c;所…

==Redis淘汰策略(内存满了触发)==

好的&#xff0c;面试官。这个问题我需要从三个方面来回答。第一个方面&#xff1a; 当 Redis 使用的内存达到 maxmemory 参数配置的阈值的时候&#xff0c;Redis 就会根据配置的内存淘汰策略。 把访问频率不高的 key 从内存中移除。maxmemory 默认情况是当前服务器的最大内存…

html5实现个人网站源码

文章目录 1.设计来源1.1 网站首页页面1.2 个人工具页面1.3 个人日志页面1.4 个人相册页面1.5 给我留言页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/139564407 ht…

Golang | Leetcode Golang题解之第141题环形链表

题目&#xff1a; 题解&#xff1a; func hasCycle(head *ListNode) bool {if head nil || head.Next nil {return false}slow, fast : head, head.Nextfor fast ! slow {if fast nil || fast.Next nil {return false}slow slow.Nextfast fast.Next.Next}return true }

unity到小游戏instantGame(流程演示,非内容制作 亲测可用)

unity到小游戏instantGame&#xff08;开发流程演示&#xff0c;非内容制作 亲测可用&#xff09; 写在前面直接 写在前面 instantGame 后妈级教学&#xff0c;主打一个填自己的坑&#xff0c;有问题下方评论交流 根据此教程使用后的一点心得记录和可能出现的问题补充&#xf…

vue面试题四

一、请解释v-show和v-if指令的区别&#xff1f; v-show 和 v-if 是 Vue.js 中用于控制元素显示与隐藏的两个常用指令&#xff0c;但它们的工作方式和性能表现有所不同。以下是它们之间的主要区别&#xff1a; 1. 工作原理 v-if&#xff1a; v-if 是“真实”的条件渲染&#x…

SpringBoot与Mybatis-plus实战

随着互联网技术的快速发展&#xff0c;企业级应用对开发效率和性能的要求越来越高。Spring Boot 作为一款快速开发框架&#xff0c;以其简洁、快速、配置方便等优点&#xff0c;得到了广泛的应用。而 MyBatis-Plus 作为 MyBatis 的增强工具&#xff0c;在简化开发、提高效率方面…

在 .NET Core 中构建工作服务和调度运行

介绍 .NET Core 中的工作服务已成为构建持续运行并执行各种任务的后台服务的强大机制。本文提供了有关创建工作服务的分步指南&#xff0c;深入研究了其演变过程&#xff0c;并阐明了代码片段以及执行过程。 工人服务的演变 工作服务是 .NET Core 旅程的延续&#xff0c;它源…

设计随笔 ---- ADR4525 篇

ADR4525一颗超低噪声、高精度2.5V基准电压源&#xff1b; Fluke 17B准确度指标&#xff1a; ADR4525指标&#xff1a; Fluke 17B测试结果&#xff1a; 2.5V的基准&#xff0c;输出只有2.477V&#xff0c;其实这么高精度的电压基准用3位半的万用表来测试本身就是一个错误&#…

【代码随想录】栈

一刷时间&#xff1a;6月8日–6月9日 用栈实现队列 class MyQueue(object):def __init__(self):self.stack_in[]self.stack_out[]def push(self, x):self.stack_in.append(x)def pop(self):if self.stack_out:return self.stack_out.pop()else:while self.stack_in:self.stac…

如何获取MySQL中表的大小?(官方校正版)

与大多数关系数据库一样&#xff0c;MySQL 提供了有关数据库本身的有用元数据。虽然大多数其他数据库将此信息称为 catalog&#xff0c; 但MySQL 官方文档INFORMATION_SCHEMA 将元数据 称为 tables。 目录 1 列出单个数据库中的单表大小 2 列出所有数据库中的所有表大小 以下…

【C语言】宏详解(下卷)

前言 紧接上卷&#xff0c;我们继续来了解宏。 宏替换的规则 1.在调用宏时&#xff0c;首先对参数进行检查&#xff0c;看看是否包含任何由#define定义的符号。如果是&#xff0c;它们首先被替换。 2.替换文本随后被插入到程序中原来文本的位置。对于宏&#xff0c;参数名被他…

Matlab 2024a 建模基础知识全面指南

一、Matlab简介 1. Matlab是什么&#xff1f; Matlab&#xff08;Matrix Laboratory&#xff09;是由MathWorks公司开发的一个高性能的数值计算环境和编程语言。它以其强大的矩阵运算能力、丰富的工具箱和便捷的数据可视化功能而闻名&#xff0c;广泛应用于科学研究、工程模拟…

WPF 简单页面切换示例

原理比较简单&#xff0c;但是有个坑&#xff0c;为了使界面能够正确更新&#xff0c;记得使用 INotifyPropertyChanged 接口来实现属性更改通知。 <Window x:Class"PageTest.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation&…

23.汽水兑奖

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动&#xff0c;旨在激发青少年对学习人工智能与算法设计的热情与兴趣&#xff0c;提升青少年科学素养&#xff0c;引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/106 题目描…

Elasticsearch:Open Crawler 发布技术预览版

作者&#xff1a;来自 Elastic Navarone Feekery 多年来&#xff0c;Elastic 已经经历了几次 Crawler 迭代。最初是 Swiftype 的 Site Search&#xff0c;后来发展成为 App Search Crawler&#xff0c;最近又发展成为 Elastic Crawler。这些 Crawler 功能丰富&#xff0c;允许以…

鞠小云张霖浩闪耀北京广播电视台春晚发布会,豪门姐弟感爆棚

昨日&#xff0c;2025年北京广播电视台“追梦春晚”全国海选发布会在杭州举行&#xff0c;中国内地青年女演员鞠小云同人气幕后张霖浩&#xff0c;受主办方盛情邀请出席本次活动。从现场流露出的照片中可以看出&#xff0c;鞠小云一袭白色长裙灵动温婉素雅&#xff0c;而张霖浩…

27.机会成本

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/677 题目描述 明天有 𝑛n 门考试,今晚只…