内核模块2 | 学习笔记

简介: 快速学习模块编写2

开发者学堂课程【物联网开发-Linux 驱动开发实操演练:内核模块2】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/657/detail/10870


内核模块2


内容介绍:

一、模块编写三要素

二、入口函数的使用介绍

三、出口函数的使用介绍

四、编写内核模块的准备工作

五、编写内核模块


一、模块编写三要素

1. 入口(加载)

Module_init(入口函数名);

2. 出口(卸载)

Module_exit(卸载函数名);

3. GPL协议申明

MODULE_LICENSE(GPL)


二、入口函数的使用介绍

1.观察入口函数

在 source insight 中搜索 module_init和 module_exit,观察内核里面其他的驱动如何使用内核模块从 module_init 和 module_exit,搜索如图所示:

图片1.png

观察发现,内核里面有很多驱动在使用模块三要素。

会发现在使用 module_init 时,会发现使用了一个其他函数:nmikbd_init,如图:

对于这个函数,需要观察它的返回值是否为 init,形参是否为 void。

总结发现:入口函数的返回值是init 类型+函数名,它的形参为 void。

图片2.png

因此需要分装一个函数名,传递给module_init的宏,注册到内核里

platform_set drvdata(pdev.NULL)

free_irq(IRQ_AMIGA_CIAASP,dev

input_unregister_device(dev);

return 0;

static structplatform_driver amikbd_driver =《

remove exit_p(amikbd_remove)

driver

.name amiga-keyboard",

Owner THIS_MODULE,

),

);static int __init amikbd_init(void)

return platform_driver_probe(&amikbd_driver, amikbd_probe);

module_init(amikbd_init);

static void __exit amikbd_exit(void)

platform_driver_unregister(&amikbd_driver);

module_exit(amikbd_exit);

MODULE ALIAS(、nlatform:amiea-kevhoard!)

2. 编写内核模块的入口函数

在编写的时候,加上--init,作用是将地址统一放在--init 的段里面,统一进行加载。

Module_init(入口函数名);

Int  __init xx_func(void)

(

)


三、出口函数的使用介绍

1.观察出口函数

在内核里面搜素 module_exit,内核中 exit 较多,简单搜索即可

image.png

找到一个入口,进入随机找一个出口函数

If  acpt ac dir)

return -ENODEV:

end1f

result= acpi_bus_register_driver(&acpi_ac_driver); (result e)(

5 CONFIG ACPI PROCFS POWER

If  acpi_unlock_ac_dir(acpi_ac_dir);

return -ENODEV;

return

static void exitacpi_ac_exit(void)

67  acpi bus unregister.driver(&acpi driver

8:

9 ifdef CONFIG ACPI PROCFS POWER

B: acpi unlock ac dir(acpt acdir);

123 #endif

return;

5:

6:module_init(acpi_ac_init);

7:module_exit(acpi_ac_exit);

观察多个例子发现,出口函数和返回值都为void。

2.编写出口函数的内核模块

对于出口函数来说,数据类型为 void1+函数名+(void),再加上--exit 的说明,和入口函数的 init 相对应,放在--exit 的段里面:

出口(卸载)

Module_exit(卸载函数名);

Void__exit xxx_func(void)

因此在书写内核模块时,定义一个--init 类型的函数和--exit 类型的函数传入进服务器,最后再注册一个 GPL 申明。

 

四、编写内核模块的准备工作

编写内核模块,需要用到 module_exit 、module_init 和 module_LICENSE 的宏,也由内核提供。

因此需要寻找内核在哪里申明或者定义了这些函数,如果一个宏函数在一个地方进行定义,在同一个地方进行申明,那么则称这个宏函数为该区域函数。

进入 Linux 内核中,找到 include 中,有一个 Linux,在 Linux 中找到 init。

如图:

image.png

在里面寻找 module_init:

madte tnle/I eithee cslledduring do_initcalls() (ff

Insertion time (1f Therecanon

be one per

delvereit entrvnodnt

unct onto be runmhen driver Is reaaved

code

driver is staticelly

eeendled the fect.

There be one per

观察发现,该函数使用了函数宏。因此在使用这俩个函数的时候,应该包含这个同介 。

关于 module-LICENSE ,则存在与 Linux 中。

image.png

综上,找到了内核模块的同文件。


找到了内核模块的同文件和函数类型之后,即可以编写一个内核模块:

1.入口(加载)

module init(入口函数名);int initxxx func(void)

2.出口(卸载)

module exit(卸载函数名);void exitXXXfunc(void)

3.GPL 协议申明

MODULELICENSE("GPL");

 

五、编写内核模块

在编写的时候,可使用任意一个编辑器进行编辑,编写完成之后,则有了.c 即源文件。这里以 source insight 为例。

新建一个 demo.c:创建好文件之后保存好。

1. 第一步:包含源文件:

1:#include

2: #include

3:

4:

5:

6:module_init();

7:module_exit();

8:MODULE_LICENSE(GPL);

1:#include

2: #include

这俩个同文件调用之后,接下来调用同文件里面定义的宏。

定义宏分为三要素:入口函数,出口函数和申明。

1:#include

2: #include

3:

4:

5:

6:module_init();

7:module_exit();

8:MODULE_LICENSE(GPL);

接下来需要对 module_exit 和 module_init 写一个入口和出口函数,取名为“dmo__init”,再在前面加上__init 的说明

有返回值,用 return 返回0,再上传到 module.init 的宏里面。

对于__exit 类型,同理:

1:#include

2: #include

3:

4:

5:int _init demo_init(void)

6:{

7:     return 0

8: }

9:

10:

11:

12:

13:module_init();

14:module_exit();

15:MODULE_LICENSE(GPL);

到这步为止,内核模块编写完成,接下来剩下来的内容需要在 demo_init 和 demo_exit 里面去编写完成。

检查 demo 是否正在执行,加上一条打印语句进行调试。

使用 printk(),格式化输出,不定参数。打印级别为八种,如果打印级别比控制级别高的话,可以直接打印出来;如果比控制级别低,不打印,放在消息日志里面。 

同时打印级别可以省略掉不写,printk 可以直接当做 printf 去进行使用。输入语句为:

Printk(”---%s---%s---%d---\m,__,__func__,__(LINE__);

退出的时候也需要进行打印,在退出时可以看到 demo.init 被调用,在卸载时,demo.exit 被调用。

#include

#include

int _init demo init(void)

printk -%s---%s---%d---\n", FILE func LINE

return e;

I

rvoid exitdemo_exit(void)

printk("---%s---%s---%d---\n", FILE func LINE

module_init(demo_init);

moduleexit(demo_exit);

MODULELICENSE("GPL")

以上,内核模块全部编写完成。

相关文章
|
1月前
|
人工智能 Python
[oeasy玩python教程]104衔尾蛇贯穿古今:传统首尾吟与 AI MIDI 作曲的韵律共鸣
本文以“回环诗”为引,从音乐旋律模进到诗歌首尾呼应,探讨了“首尾吟”这一独特诗体。通过邵雍、程颢等北宋文人的作品,结合Python代码验证诗歌结构,并延伸至《爱莲说》《太极图》中的哲学循环观,揭示历史与艺术中“周而复始、螺旋上升”的规律。同时,对比电影、民歌(如《小星星》《茉莉花》)中的首尾闭环手法,展现跨领域的回环之美。
78 1
|
Linux 数据安全/隐私保护
JumpServer的资产管理
文章介绍了如何使用JumpServer进行资产管理,包括创建系统用户、管理用户以及资产,并提供了操作步骤和测试连接性的指导。
345 0
JumpServer的资产管理
|
数据采集 存储 数据安全/隐私保护
拓展网络技能:利用lua-http库下载www.linkedin.com信息的方法
本文介绍如何使用Lua和lua-http库抓取LinkedIn信息,强调了Lua在爬虫开发中的应用。通过配置亿牛云爬虫代理解决IP封锁问题,实现步骤包括安装库、配置代理、发送HTTP请求、解析响应及提取信息。提供的Lua代码示例展示了下载和存储LinkedIn信息的过程。实验成功展示了Lua爬虫的可行性,但也指出需考虑反爬虫策略以应对实际挑战。
208 1
拓展网络技能:利用lua-http库下载www.linkedin.com信息的方法
|
缓存 网络协议 安全
Linux:设置/修改linux主机名+hosts映射+主机名解析机制分析+DNS域名劫持
Linux:设置/修改linux主机名+hosts映射+主机名解析机制分析+DNS域名劫持
1687 0
Linux:设置/修改linux主机名+hosts映射+主机名解析机制分析+DNS域名劫持
|
机器学习/深度学习 人工智能 安全
从云技术风向标看2022企业数字化转型战略方向
从云技术风向标看2022企业数字化转型战略方向
247 0
|
SQL Java 关系型数据库
JSP+MySQL校园新闻网站(3)–数据库与java项目创建
本文目录 0. 前言 1. 新建数据库 2. 新建项目 3. 导入jar包 4. 准备就绪
250 0
JSP+MySQL校园新闻网站(3)–数据库与java项目创建
|
JavaScript 前端开发 iOS开发
使用Python编写iOS原生应用的框架设计思考(首篇一)
使用Python编写iOS原生应用的框架设计思考(首篇)
337 0
使用Python编写iOS原生应用的框架设计思考(首篇一)
|
JSON JavaScript 前端开发
1-SIII--Json在Android中的使用--Gson
Json 是什么? 一开始在Android,对我来说它是一个有规则个字符串。 当我深入JavaScript后,感觉它越来越有意思,当成一个对象来用,属性、方法都能往里塞。
1435 0
|
Web App开发 Windows
三张照片解决--win10系统的edge浏览器设置为浏览器IE8,IE7,IE9---完美解决 费元星
主要思想:         第二种方法:     参考文档: 1、可以在系统盘的C:\Program Files\Internet Explorer中找到iexplore.exe,然后将其发送到桌面快捷方式即     可,其就是ie浏览器。
1543 0