08 redis经典五种数据类型及底层实现

news2024/11/23 21:06:44

redis是字典数据库KV键值对是什么

  • redis 是 key-value 存储系统,其中key类型一般为字符串,value 类型则为redis对象(redisObject)
  • 在这里插入图片描述
  • Redis定义了redisObjec结构体来表示string、hash、list、set、zset等数据类型
    • C语言struct结构体语法简介
    • 在这里插入图片描述
    • 在这里插入图片描述
    • Redis 中每个对象都是一个 redisObject 结构
    • 字典、KV是什么
    • 在这里插入图片描述
    • 在这里插入图片描述
    • 每个键值对都会有一个dictEntry
  • redisObject +Redis数据类型+Redis 所有编码方式(底层实现)三者之间的关系
  • 在这里插入图片描述

5大结构底层C语言源码分析

从set hello world说起

  • set hello word为例,因为Redis是KV键值对的数据库,每个键值对都会有一个dictEntry(源码位置:dict.h),里面指向了key和value的指针,next 指向下一个 dictEntry。
  • key 是字符串,但是 Redis 没有直接使用 C 的字符数组,而是存储在redis自定义的 SDS中。
  • value 既不是直接作为字符串存储,也不是直接存储在 SDS 中,而是存储在redisObject 中。
  • 实际上五种常用的数据类型的任何一种,都是通过 redisObject 来存储的。
  • 在这里插入图片描述
  • 每个键值对都会有一个dictEntry

redisObjec结构的作用

RedisObject各字段的含义

  • 在这里插入图片描述
  • 在这里插入图片描述
  • 4位的type表示具体的数据类型
  • 4位的encoding表示该类型的物理编码方式见下表,同一种数据类型可能有不同的编码方式。
    (比如String就提供了3种:int embstr raw)
  • lru字段表示当内存超限时采用LRU算法清除内存中的对象。
  • refcount表示对象的引用计数。
  • ptr指针指向真正的底层数据结构的指针。

案例

在这里插入图片描述

数据类型以及数据结构的关系

程序员写代码时脑子底层思维

在这里插入图片描述

String数据结构介绍

3大编码格式
  • int
    • 保存long 型(长整型)的64位(8个字节)有符号整数
    • 只有整数才会使用 int,如果是浮点数, Redis 内部其实先将浮点数转化为字符串值,然后再保存。
  • embstr
    • 代表 embstr 格式的 SDS(Simple Dynamic String 简单动态字符串),保存长度小于44字节的字符串
    • EMBSTR 顾名思义即:embedded string,表示嵌入式的String
  • raw
    • 保存长度大于44字节的字符串
3大编码案例

在这里插入图片描述

C语言中字符串的展现
- Redis没有直接复用C语言的字符串,而是新建了属于自己的结构-----SDS
- 在Redis数据库里,包含字符串值的键值对都是由SDS实现的(Redis中所有的键都是由字符串对象实现的即底层是由SDS实现,Redis中所有的值对象中包含的字符串对象底层也是由SDS实现)。
Redis为什么重新设计一个 SDS 数据结构?
  • C语言没有Java里面的String类型,只能是靠自己的char[]来实现,字符串在 C 语言中的存储方式,想要获取 「Redis」的长度,需要从头开始遍历,直到遇到 ‘\0’ 为止。所以,Redis 没有直接使用 C 语言传统的字符串标识,而是自己构建了一种名为简单动态字符串 SDS(simple dynamic string)的抽象类型,并将 SDS 作为 Redis 的默认字符串。
  • 在这里插入图片描述
三大编码
  • INT 编码格式
    • set k1 123
    • 当字符串键值的内容可以用一个64位有符号整形来表示时,Redis会将键值转化为long型来进行存储,此时即对应 OBJ_ENCODING_INT 编码类型。内部的内存结构表示如下:
    • 在这里插入图片描述
    • Redis 启动时会预先建立 10000 个分别存储 0~9999 的 redisObject 变量作为共享对象,这就意味着如果 set字符串的键值在 0~10000 之间的话,则可以 直接指向共享对象 而不需要再建立新对象,此时键值不占空间!
    • 在这里插入图片描述
  • EMBSTR编码格式
    • set k1 abc
    • 在这里插入图片描述
    • 对于长度小于 44的字符串,Redis 对键值采用OBJ_ENCODING_EMBSTR 方式,EMBSTR 顾名思义即:embedded string,表示嵌入式的String。从内存结构上来讲 即字符串 sds结构体与其对应的 redisObject 对象分配在同一块连续的内存空间,字符串sds嵌入在redisObject对象之中一样。
    • 在这里插入图片描述
    • 在这里插入图片描述
  • RAW 编码格式
    • set k1 大于44长度的一个字符串,随便写
    • 当字符串的键值为长度大于44的超长字符串时,Redis 则会将键值的内部编码方式改为OBJ_ENCODING_RAW格式,这与OBJ_ENCODING_EMBSTR编码方式的不同之处在于,此时动态字符串sds的内存与其依赖的redisObject的内存不再连续了
    • 在这里插入图片描述
  • 明明没有超过阈值,为什么变成 raw 了
    • 在这里插入图片描述
  • 转变逻辑图
    • 在这里插入图片描述
案例结论
  • 只有整数才会使用 int,如果是浮点数, Redis 内部其实先将浮点数转化为字符串值,然后再保存。
  • embstr 与 raw 类型底层的数据结构其实都是 SDS (简单动态字符串,Redis 内部定义 sdshdr 一种结构)。
  • 在这里插入图片描述
  • 在这里插入图片描述
总结
  • Redis内部会根据用户给的不同键值而使用不同的编码格式,自适应地选择较优化的内部编码格式,而这一切对用户完全透明!
  • 在这里插入图片描述

Hash数据结构介绍

案例

  • hash-max-ziplist-entries:使用压缩列表保存时哈希集合中的最大元素个数。
  • hash-max-ziplist-value:使用压缩列表保存时哈希集合中单个元素的最大长度。
  • Hash类型键的字段个数 小于 hash-max-ziplist-entries 并且每个字段名和字段值的长度 小于 hash-max-ziplist-value 时,Redis才会使用 OBJ_ENCODING_ZIPLIST来存储该键,前述条件任意一个不满足则会转换为 OBJ_ENCODING_HT的编码方式
  • 在这里插入图片描述
  • 在这里插入图片描述
结论
  • 哈希对象保存的键值对数量小于 512 个;
  • 所有的键值对的健和值的字符串长度都小于等于 64byte(一个英文字母一个字节) 时用ziplist,反之用hashtable
  • ziplist升级到hashtable可以,反过来降级不可以
    • 一旦从压缩列表转为了哈希表,Hash类型就会一直用哈希表进行保存而不会再转回压缩列表了。
    • 在节省内存空间方面哈希表就没有压缩列表高效了。
流程

在这里插入图片描述

源码分析

ziplist.c
ziplist什么样
  • ziplist是一个经过特殊编码的双向链表,它不存储指向上一个链表节点和指向下一个链表节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能,来换取高效的内存空间利用率,节约内存,是一种时间换空间的思想。只用在字段个数少,字段值小的场景里面
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述
ziplist各个组成单元什么意思

在这里插入图片描述

明明有链表了,为什么出来一个压缩链表?
  • 普通的双向链表会有两个指针,在存储数据很小的情况下,我们存储的实际数据的大小可能还没有指针占用的内存大,得不偿失。ziplist 是一个特殊的双向链表没有维护双向指针:prev next;而是存储上一个 entry的长度和 当前entry的长度,通过长度推算下一个元素在什么地方。牺牲读取的性能,获得高效的存储空间,因为(简短字符串的情况)存储指针比存储entry长度更费内存。这是典型的“时间换空间”。
  • 链表在内存中一般是不连续的,遍历相对比较慢,而ziplist可以很好的解决这个问题,普通数组的遍历是根据数组里存储的数据类型找到下一个元素的(例如int类型的数组访问下一个元素时每次只需要移动一个sizeof(int)就行),但是ziplist的每个节点的长度是可以不一样的,而我们面对不同长度的节点又不可能直接sizeof(entry),所以ziplist只好将一些必要的偏移量信息记录在了每一个节点里,使之能跳到上一个节点或下一个节点。
  • 头节点里有头节点里同时还有一个参数 len,和string类型提到的 SDS 类似,这里是用来记录链表长度的。因此获取链表长度时不用再遍历整个链表,直接拿到len值就可以了,这个时间复杂度是 O(1)
  • 在这里插入图片描述
压缩列表节点的构成
  • 压缩列表是 Redis 为节约空间而实现的一系列特殊编码的连续内存块组成的顺序型数据结构,本质上是字节数组
  • 在模型上将这些连续的数组分为3大部分,分别是header+entry集合+end
    • 其中header由zlbytes+zltail+zllen组成
    • entry是节点
    • zlend是一个单字节255(1111 1111),用做ZipList的结尾标识符。见下: 压缩列表结构:由zlbytes、zltail、zllen、entry、zlend这五部分组成
    • 在这里插入图片描述
    • zlbytes 4字节,记录整个压缩列表占用的内存字节数。
      zltail 4字节,记录压缩列表表尾节点的位置。
      zllen 2字节,记录压缩列表节点个数。
      zlentry 列表节点,长度不定,由内容决定。
      zlend 1字节,0xFF 标记压缩的结束。
zlentry实体结构解析

在这里插入图片描述

  • 压缩列表zlentry节点结构:每个zlentry由前一个节点的长度、encoding和entry-data三部分组成
  • 在这里插入图片描述
  • 前节点:(前节点占用的内存字节数)表示前1个zlentry的长度,prev_len有两种取值情况:1字节或5字节。取值1字节时,表示上一个entry的长度小于254字节。虽然1字节的值能表示的数值范围是0到255,但是压缩列表中zlend的取值默认是255,因此,就默认用255表示整个压缩列表的结束,其他表示长度的地方就不能再用255这个值了。所以,当上一个entry长度小于254字节时,prev_len取值为1字节,否则,就取值为5字节。
  • enncoding:记录节点的content保存数据的类型和长度。
  • content:保存实际数据内容
  • 在这里插入图片描述
ziplist存取情况

在这里插入图片描述

t_hash.c

被称为字典(dictionary),它是一个数组+链表的结构
在这里插入图片描述

OBJ_ENCODING_HT 编码分析
  • OBJ_ENCODING_HT 这种编码方式内部才是真正的哈希表结构,或称为字典结构,其可以实现O(1)复杂度的读写操作,因此效率很高。
  • 每个键值对都会有一个dictEntry
  • 在 Redis内部,从 OBJ_ENCODING_HT类型到底层真正的散列表数据结构是一层层嵌套下去的,组织关系见面图:
  • 在这里插入图片描述

List数据结构介绍

案例

在这里插入图片描述

  • ziplist压缩配置:list-compress-depth 0
    • 表示一个quicklist两端不被压缩的节点个数。这里的节点是指quicklist双向链表的节点,而不是指ziplist里面的数据项个数
    • 参数list-compress-depth的取值含义如下:
      0: 是个特殊值,表示都不压缩。这是Redis的默认值。
      1: 表示quicklist两端各有1个节点不压缩,中间的节点压缩。
      2: 表示quicklist两端各有2个节点不压缩,中间的节点压缩。
      3: 表示quicklist两端各有3个节点不压缩,中间的节点压缩。
      依此类推…
  • ziplist中entry配置:list-max-ziplist-size -2
    • 当取正值的时候,表示按照数据项个数来限定每个quicklist节点上的ziplist长度。比如,当这个参数配置成5的时候,表示每个quicklist节点的ziplist最多包含5个数据项。当取负值的时候,表示按照占用字节数来限定每个quicklist节点上的ziplist长度。这时,它只能取-1到-5这五个值,
      每个值含义如下:
      -5: 每个quicklist节点上的ziplist大小不能超过64 Kb。(注:1kb => 1024 bytes)
      -4: 每个quicklist节点上的ziplist大小不能超过32 Kb。
      -3: 每个quicklist节点上的ziplist大小不能超过16 Kb。
      -2: 每个quicklist节点上的ziplist大小不能超过8 Kb。(-2是Redis给出的默认值)
      -1: 每个quicklist节点上的ziplist大小不能超过4 Kb。

List的一种编码格式

  • list用quicklist来存储,quicklist存储了一个双向链表,每个节点都是一个ziplist
  • 在这里插入图片描述
  • quicklist
    • 在低版本的Redis中,list采用的底层数据结构是ziplist+linkedList;
    • 高版本的Redis中底层数据结构是quicklist(它替换了ziplist+linkedList),而quicklist也用到了ziplist。
    • quicklist 实际上是 zipList 和 linkedList 的混合体,它将 linkedList按段切分,每一段使用 zipList 来紧凑存储,多个 zipList 之间使用双向指针串接起来。
    • 在这里插入图片描述

源码分析

  • quicklist.h,head和tail指向双向列表的表头和表尾
  • 在这里插入图片描述
  • 在这里插入图片描述
  • quicklistNode中的*zl指向一个ziplist,一个ziplist可以存放多个元素
  • 在这里插入图片描述
  • 在这里插入图片描述

Set数据结构介绍

案例

  • Redis用intset或hashtable存储set。如果元素都是整数类型,就用intset存储。
  • 如果不是整数类型,就用hashtable(数组+链表的存来储结构)。key就是元素的值,value为null。
  • 在这里插入图片描述

ZSet数据结构介绍

案例

  • 当有序集合中包含的元素数量超过服务器属性 server.zset_max_ziplist_entries 的值(默认值为 128 ),或者有序集合中新添加元素的 member 的长度大于服务器属性。server.zset_max_ziplist_value 的值(默认值为 64 )时,redis会使用跳跃表作为有序集合的底层实现。否则会使用ziplist作为有序集合的底层实现
  • 在这里插入图片描述
  • 在这里插入图片描述

小总结

redis数据类型以及数据结构的关系

在这里插入图片描述

不同数据类型对应的底层数据结构

  1. 字符串
    int:8个字节的长整型。
    embstr:小于等于44个字节的字符串。
    raw:大于44个字节的字符串。
    Redis会根据当前值的类型和长度决定使用哪种内部编码实现。

  2. 哈希
    ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64 字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的 结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。
    hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使 用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

  3. 列表
    ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置 (默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时 (默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使 用。
    linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用 linkedlist作为列表的内部实现。quicklist ziplist和linkedlist的结合以ziplist为节点的链表(linkedlist)

  4. 集合
    intset(整数集合):当集合中的元素都是整数且元素个数小于set-max- intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。
    hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

  5. 有序集合
    ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist- entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配 置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist 可以有效减少内存的使用。
    skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作 为内部实现,因为此时ziplist的读写效率会下降。

redis数据类型以及数据结构的时间复杂度

在这里插入图片描述

skiplist跳表面试题

是什么

  • 跳表是可以实现二分查找的有序链表
  • skiplist是一种以空间换取时间的结构。
  • 由于链表,无法进行二分查找,因此借鉴数据库索引的思想,提取出链表中关键节点(索引),先在关键节点上查找,再进入下层链表查找。
  • 提取多层关键节点,就形成了跳跃表
  • 总结来讲 跳表 = 链表 + 多级索引

说说链表和数组的优缺点?为什么引出跳表

痛点

在这里插入图片描述
在这里插入图片描述

跳表的时间复杂度

  • 首先每一级索引我们提升了2倍的跨度,那就是减少了2倍的步数,所以是n/2、n/4、n/8以此类推;
  • 第 k 级索引结点的个数就是 n/(2^k);
  • 假设索引有 h 级, 最高的索引有2个结点;n/(2^h) = 2, 从这个公式我们可以求得 h = log2(N)-1;
  • 所以最后得出跳表的时间复杂度是O(logN)

跳表的空间复杂度

  • 首先原始链表长度为n
  • 如果索引是每2个结点有一个索引结点,每层索引的结点数:n/2, n/4, n/8 … , 8, 4, 2 以此类推
  • 或者所以是每3个结点有一个索引结点,每层索引的结点数:n/3, n/9, n/27 … , 9, 3, 1 以此类推;
  • 所以空间复杂度是O(n);

优缺点

  • 跳表是一个最典型的空间换时间解决方案,而且只有在数据量较大的情况下才能体现出来优势。而且应该是读多写少的情况下才能使用,所以它的适用范围应该还是比较有限的
  • 维护成本相对要高 - 新增或者删除时需要把所有索引都更新一遍;最后在新增和删除的过程中的更新,时间复杂度也是O(log n)

常见面试题

  • redis是单线程,这个是如何理解的,作者为什么这样设计?
  • redis的跳跃列表了解吗?这个数据结构有什么特点
  • redis项目里面怎么用?redis的数据结构都了解哪些?布隆过滤器怎么用?
  • redis的多路io复用如何理解,为什么单线程还可以抗那么高的qps
  • redis的zset底层实现
  • redis的跳表说一下,解决了那些问题,时间复杂度和空间复杂度如何

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

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

相关文章

【华为机试】死记硬背没思路?一般人我劝你还是算了吧

大家好,我是哪吒。 五月份之前,如果你参加华为OD机试,收到的应该是2022Q4或2023Q1,这两个都是A卷题。 5月10日之后,很多小伙伴收到的是B卷,那么恭喜你看到本文了,抓紧刷题吧。B卷新题库正在更…

Spring依赖注入解析

目录 依赖注入大致要点 依赖注入大致流程 Bean的预实例化 doGetBean createBean 完备Bean的创建过程 createBeanInstance populateBean 依赖注入大致要点 Spring在Bean实例的创建过程中做了很多精细化控制finishBeanFactoryInitialization方法里面的preInstantiateSing…

【计算机网络复习】第六章 局域网 LAN

局域网( LAN)概述 LAN的特点 • 覆盖范围小 房间、建筑物、园区范围 • 高传输速率 10Mb/s~1000Mb/s • 低误码率 10-8 ~ 10-11 • 拓扑:总线型、星形、环形 • 介质:UTP、Fiber、C…

6年测试经验之谈,为什么要做自动化测试?

一、自动化测试 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。 个人认为,只要能服务于测试工作,能够帮助我们提升工作效率的,不管是所谓的自动化工具,还是简单的SQL 脚本、批处理脚本,还是自己编写…

智能优化算法:指数分布优化算法-附代码

智能优化算法:指数分布优化算法 文章目录 智能优化算法:指数分布优化算法1.指数分布优化算法1.1种群初始化1.2EDO开发1.3EDO探索 2.实验结果3.参考文献4.Matlab5.python 摘要:指数分布优化算法(Exponential distribution optimize…

全新好用的窗口置顶工具WindowTop

打开WindowTop软件,所有已打开的窗口都会在左上角出现一个置顶栏,点击置顶栏的置顶复选框即可置顶窗口或取消窗口。   在WindowTop软件的置顶栏一项里可以自由调整置顶栏的元素(包含增删位置)。   可改变置顶栏的外观&#x…

剖析ffmpeg视频解码播放:时间戳的处理

一、视频播放基础理论 1.1 视频编码和解码基础 视频编码和解码是视频播放的基础,理解它们的工作原理对于深入理解视频播放至关重要。在这一部分,我们将详细介绍视频编码和解码的基础知识。 视频编码(Video Encoding)是将原始视…

离散数学_十章-图 ( 5 ):连通性 - 上

📷10.5 图的连通性 1. 通路1.1 通路1.2 回路1.3 其他术语 2. 无向图的连通性2.1 无向图的连通与不连通2.2 定理2.3 连通分支 3. 图是如何连通的3.1 割点( 关节点)3.2 割边( 桥)3.3 不可分割图3.4 𝑘(&#…

Linux内核模块开发 第 5 章

The Linux Kernel Module Programming Guide Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang译 断水客(WaterCutter) 5 预备知识(Preliminaries) 5.1 模块的入口函数和出口函数 C 程序通常从 ma…

建筑与建材行业相关深度学习数据集大合集

近期又整理了一批建筑与建材行业相关深度学习数据集,分享给大家。废话不多说,直接上干货!! 1、埃及的地标数据集 自从历史开始以来,埃及一直是许多文明、文化和非常著名的地标的家园,现在你(和你的ML模型…

守护进程【Linux】

文章目录 前导知识shell、terminal、console进程组作业会话测试 会话控制jobfgbgps 守护进程作用查看守护进程创建守护进程 前导知识 shell、terminal、console terminal(终端)是一种可以和计算机交互的设备,通常有键盘和显示器&#xff0c…

RocketMq 的基本知识1

一RocketMq的基本知识 1.1 RocketMq的基本知识 MQ , Message Queue ,是一种提供 消息队列服务 的中间件,也称为消息中间件。 1.2 作用 1.流量消峰 2.异步传输 3.日志收集 1.3 核心概念 1消息: 消息是指,消息系统所…

基于内存操作的Redis数据库--详解

目录 基本概念 基本操作 redis的五个基本类型 Redis-key(不区分大小写) 字符串 string Redis的特殊类型 geospatial地理空间 事务 Redis的持久化 RDB(.rdb) 触发机制 优点 缺点 AOF(.aof) 优点…

冈萨雷斯DIP第8章知识点

8.1 基础 图像中的冗余 编码冗余:用于表示灰度的8比特编码所包含的比特数,要比表示该灰度所需要的比特数多。可通过变长编码来解决。 空间和时间冗余:与相邻像素相似(图像);时间:相邻帧中的像素(视频)。可以使用行程…

缺陷管理利器推荐:介绍几款好用的缺陷管理工具

缺陷管理是项目管理工作中的重要环节。Excel表格是国内团队常用的缺陷管理工具,具备上手容易,免费的优点,不过也存在协同不便,不易管理,效率低的不足之处。 一套缺陷管理工具可以帮助我们进行规范化自动化的缺陷管理&a…

LearnOpenGL-高级OpenGL-8.高级GLSL

本人初学者,文中定有代码、术语等错误,欢迎指正 文章目录 高级GLSLGLSL的内建变量在顶点着色器的内建变量gl_PointSizegl_VertexID 在片段着色器的内建变量gl_FragCoordgl_FrontFacinggl_FragDepth 接口块Uniform缓冲对象Uniform块布局使用Uniform缓冲简…

关于惠普M277打印机手动双面打印和自动双面打印设置

一.手动双面打印设置​​​​​​​ 1.键盘WINR,在运行框输入“control”,回车或者点击确定。 ​​​​​​​ 2.在控制面板找到设备和打印机,点击进去。 3.找到HP M277字样的打印机,右键选择打印机属性。 4.点击设…

有关部门信息表与员工信息表的常用SQL应用语句实现汇总

背景条件 已知有员工信息表(emp)和部门信息表(dept),具体表的信息如下: 员工信息表emp: 列名类型其他备注empnoDECIMAL(4)主键员工编号enameVARCHAR2(10)员工姓名jobVARCHAR2(9)工种mgrDECIM…

实现第一个内核程序的Hello World

背景 在内核的开发中,总要先入个门。那么就要来编写第一个内核程序 入门 一个 module_init 程序是Linux内核模块的一部分,通过module_init 方法就能将程序载入内核。 module_init 方法需要以下步骤 编写module_init 的代码,并将其保存为…