第7章 模块(2)

目录

7.3 插入和删除模块

7.3.1 模块的表示

7.3.2 依赖关系和引用

7.3.3 模块的二进制结构

7.3.4 插入模块

7.3.5 移除模块


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

7.3 插入和删除模块

两个系统调用:

        init_module:插入模块。

        delete_module:删除模块。

request_module 函数:非系统调用

作用:

        1. 内核中加载一个模块。

        2. 实现热插拔。

7.3.1 模块的表示

每个模块都有一个 struct module 实例:

struct    module {

        enum module_state         state;         //模块的装载状态

        struct list_head                 list;           //连接内核所有模块

        struct kernel_symbol      *syms;      //该模块导出的符号及其内存地址。

        unsigned int                      num_syms;

        struct module_ref              ref;

                //该模块的引用计数。

                        module_put 时减1。

                        try_module_get 加1。

        unsigned int                      init_size, core_size;

                // 模块中__init 类型的符号大小,其余符号大小。

        unsigned int                      init_text_size, core_text_size;

        void                                   (*init)(void);         // 模块初始化时调用。

        void                                   (*exit)(void);

}

struct         kernel_symbol {

        unsigned long         value;         // 内存地址。

        const char               *name;       // 符号。

}

# cat  /proc/kallsyms:

        查看导出的所有符号。

当模块污染内核,原因:

        许可证问题。

7.3.2 依赖关系和引用

为管理模块间的依赖关系,引入如下结构体。

struct    module_use {

        struct list_head         source_list;         // 依赖本模块的模块。

        struct list_head         target_list;          // 本模块所依赖的模块。

        struct module            *source,  *target;

};

如果模块 A 依赖了模块 B 中函数,则调用:

int    add_module_usage(struct module   *a,    struct module   *b)

{

        struct module_use    *use;

        use   =   kmalloc(sizeof(*use),   GFP_ATOMIC);

        use->source   =   a;

        use->target   =   b;

        list_add(&use->source_list,   &b->source_list);

        list_add(&use->target_list,     &a->target_list);

}

already_uses:判断模块A是否使用了模块B。

int   already_uses(struct module   *a,   struct module   *b)

{

        struct module_use   *use;

        list_for_each_entry(use,   &b->source_list,   source_list)

        {

                if (use->source   ==   a) {

                        return 1;

                }

        }

}

7.3.3 模块的二进制结构

一个模块文件的格式是ELF,其特有的段有:

        1. __ksymtab段:保存内核符号表。

        2. __kcrctab段:保存导出函数的校验和。

        3. __param段:保存模块参数。

        4. __ex_table段:保存新增内核异常表。

        5. .modinfo段:保存依赖模块名称、author、描述、许可证、参数列表等。

                (modinfo命令:读取该段)

        6. .init.data,.exit.data段:

                保存__init和__exit类型的数据。

        7. .init.text,.exit_text段:

                保存__init和__exit类型的函数。

1. 初始化和清理函数

module_init(nat_init_module);

module_exit(nat_cleanup_module);

即在.init.data,.init.text,.exit.data段中定义模块的init,exit函数。

2. 导出符号

两个宏:

        EXPORT_SYMBOL:导出一般符号。

        EXPORT_SYMBOL_GPL:导出GPL兼容代码的符号。

EXPORT_SYMBOL

        原理:将相应符号放置在模块二进制文件的一个段中。

举例:将变量 a 导出到文件的 .my_test.data 段中。

        static   int   a __attribute__((section(".my_test.data")));

EXPORT_SYMBOL_PREFIX

        作用:给导出符号分配一个前缀。

        使用场景:某些特定体系架构需要。

3. 模块的信息

MODULE_INFO(tag,    info):

        作用:生成一个模块的相关信息。

        原理:使用__attribute__((section(".modinfo"))),将模块的信息保存在 .modinfo 段中。

#define     MODULE_LICENSE(_license)     MODULE_INFO(license,     _license)

#define     MODULE_ALIAS(_alias)              MODULE_INFO(alias,     _alias)

#define     MODULE_AUTHOR(_author)      MODULE_INFO(author,     _author)

宏VERMAGIC_STRING:

定义了安装模块时,需要检查的信息,若和内核不一致,则不可安装模块。

        1. SMP配置。

        2. 内核抢占配置

        3. 模块版本。

        4. 特定于体系架构的常数。

#define    VERMAGIC_STRING   \

        MODULE_VERMAGIC_SMP   \

        MODULE_VERMAGIC_PREEMPT   \

        MODULE_VERMAGIC_MODVERSIONS   \

        MODULE_ARCH_VERMAGIC   \

7.3.4 插入模块

对应系统调用:

        init_module

load_module 内容:

        1. 使用copy_from_user,将模块加载到内核空间。

        2. 重写函数和变量的地址。

        3. 在内存中组织数据。

                使用 layout_sections,判断模块的段加载到内存哪个位置。

                模块的段分为两类:

                        core 和 init。

        4. 分配内存,传输模块到内存。

        5. 检查模块许可证。

        6. 通过reslove_symbol,解决引用重定位。

7.3.5 移除模块

对应系统调用:

        delete_module

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

考研数学二战,怎么准备才能提升大?

一战70多...二战提升空间那是相当的大 我身边很多一战甚至不到60,二战成绩飙到120的,真的很猛 所以你根本不用担心是自己学数学没天赋,其实知识方法没用对而已 本人属于基础很差相当于是零基础的23考研党,经过一年备考成功上岸…

k8s集群 安装配置 Prometheus+grafana+alertmanager

k8s集群 安装配置 Prometheusgrafanaalertmanager k8s环境如下:机器规划: node-exporter组件安装和配置安装node-exporter通过node-exporter采集数据显示192.168.40.180主机cpu的使用情况显示192.168.40.180主机负载使用情况 Prometheus server安装和配置…

JayChou周杰伦的歌曲网易云音乐怎么听

听Jay自由 网易云导入 专辑介绍 周杰伦(Jay Chou)是一位著名的台湾流行歌手、词曲创作人和演员。他以其独特的音乐风格和才华横溢的创作能力而闻名于世。以下是对周杰伦所有专辑的简要介绍: 《Jay》(2000年)&#xf…

独立开发者系列(26)——域名与解析

域名(英语:Domain Name),又称网域,是由一串用点分隔的名字组成的互联网上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)。 由于IP地址不方便…

Leaflet集成wheelnav在WebGIS中的应用

目录 前言 一、两种错误的实现方式 1、组件不展示 2、意外中的空白 二、不同样式的集成 1、在leaflet中集成wheelnav 2、给marker绑定默认组件 2、面对象绑定组件 3、如何自定义样式 三、总结 前言 在之前的博客中,我们曾经介绍了使用wheelnav.js构建酷炫…

Flink底层原理解析:案例解析(第37天)

系列文章目录 一、flink架构 二、Flink底层原理解析 三、Flink应用场景解析 四、fink入门案例解析 文章目录 系列文章目录前言一、flink架构1. 作业管理器(JobManager)2. 资源管理器(ResourceManager)3. 任务管理器(Ta…

【八股系列】CSS盒模型:掌握网页布局的核心

🎉 博客主页:【剑九 六千里-CSDN博客】 🎨 上一篇文章:【Vue中的<keep-alive>组件:深入解析与实践指南】 🎠 系列专栏:【面试题-八股系列】 💖 感谢大家点赞&…

夏日狂欢水上漂流的爆笑奇遇记

【夏日狂欢,水上漂流的爆笑奇遇记 —— 月亮姐姐的“睫毛漂流记”】在这个炎炎夏日,当烈日炙烤着大地,每一寸空气弥漫着对清凉的渴望时,一场别开生面的“暑期嘉年华”正悄然掀起一场水上狂欢的浪潮。而在这场盛宴中,月…

FPGA实训报告DAY 1(Verilog HDL)

实习日志与总结 日期:2024 年 7 月 10 日 星期三 姓名:XXX 一、实习日志 上午 9:00 - 9:30 按时到达工位,参加部门早会,了解了今天的实习任务和目标,即初步学习 FPGA 简介和 Verilog 基础语法知识。 9:30 - 10:30…

springboot 集成minio,启动报错

springboot 集成 minio 8.5.10 报错 *************************** APPLICATION FAILED TO START *************************** Description: An attempt was made to call a method that does not exist. The attempt was made from the following location: io.minio.S3Base.…

在mybatis-plus中关于@insert注解自定义批处理sql导致其雪花算法失效而无法自动生成id的解决方法

受到这位作者的启发 > 原文在点这里 为了自己实现批量插入&#xff0c;我在mapper层使用insert注解写了一段自定义sql //自定义的批量插入方法 Insert("<script>" "insert into rpt_material_hour(id,sample_time,rounding_time,cur_month,machine_no…

启智畅想火车类集装箱号码识别技术,软硬件解决方案

集装箱号码识别需求&#xff1a; 实时检测车皮号、火车底盘号码、集装箱号码&#xff0c;根据火车类型分为以下三种情况&#xff1a; 1、纯车皮&#xff0c;只检测车皮号&#xff1b; 2、火车拉货箱&#xff08;半车皮&#xff09;&#xff0c;检测车皮号集装箱号码&#xff1b…

基于springboot和mybatis的RealWorld后端项目实战一之hello-springboot

新建Maven项目 注意archetype选择quickstart pom.xml 修改App.java App.java同级目录新增controller包 HelloController.java package org.example.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotatio…

拒绝废话:computed、watch和methods的区分和使用场景

computed、watch和methods是用于处理数据和响应数据变化的不同方式&#xff0c;三者之间有什么不同呢&#xff0c;贝格前端工场作为10年前端老司机&#xff0c;用浅显的语言给大家分享一下。 computed&#xff1a; computed属性是用来定义一个基于依赖的响应式属性。它会根据…

QT--控件篇四

一、对话框 在软件开发中&#xff0c;对话框&#xff08;Dialog&#xff09;是一种常见的用户界面元素&#xff0c;用于与用户进行交互和获取信息。它通常以模态或非模态的形式出现&#xff0c;模态对话框会阻止用户与应用程序的其他部分交互&#xff0c;直到对话框关闭为止&a…

Linux热键,shell含义及权限介绍

君子忧道不忧贫。 —— 孔丘 Linux操作系统的权限 1、几个常用的热键介绍1、1、[Tab]键1、2、[ctrl]-c1、3、[ctrl]-d1、4、[ctrl]-r 2、shell命令以及运行原理3、权限3、1、什么是权限3、2、权限的本质3、3、Linux中的用户3、4、Linux中文件的权限3、4、1、快速掌握修改权限的…

排序——归并排序及排序章节总结

前面的文章中 我们详细介绍了排序的概念&#xff0c;插入排序&#xff0c;交换排序与选择排序&#xff0c;大家可以通过下面的链接再去学习&#xff1a; ​​​​​​排序的概念及插入排序 交换排序 选择排序 这篇文章就详细介绍一下另一种排序算法&#xff1a;归并排序以及…

ubuntu 虚拟机扩容

在使用vmware创建的ubuntu虚拟机进行linux开发时&#xff0c;安装了docker容器&#xff0c;编译会占用很大的磁盘空间&#xff0c;不想创建新的更大空间的虚拟机linux系统&#xff0c;可以通过gparted图形化工具进行扩容&#xff0c;以下是操作方法 虚拟机设置&#xff0c;扩展…

k8s核心操作_存储抽象_K8S中使用Secret功能来存储密码_使用免密拉取镜像_k8s核心实战总结---分布式云原生部署架构搭建033

注意在看的时候一定要把 dxxxx中的xxxx换成--o----c----k----e----r 然后我们再来看一个k8s中的secret的功能,这个功能 用来存储密码的,configMap是用来存配置的 比如我们有个pod,他的镜像,如果是需要密码的,那么 我们现在是从公共仓库拉取的,如果我们从私有仓库拉取,有密码…

rust + python+ libtorch

1: 环境&#xff0c;ubuntu 1.1 rust : rust-1.79.0 &#xff08;在官方下载linux版本后&#xff0c;解压文件夹&#xff0c;内部有个install的sh文件&#xff0c;可安装&#xff09; 安装成功测试&#xff1a;cargo --version 1.2 python3.10 (直接使用apt install pytho…