当前位置: 首页 > article >正文

驱动模块--内核模块

内核模块宏都有什么,分别有什么作用?

1.__init的作用: 展开后为:__attribute__((__section_(".init.text")))实际是gcc的一个特殊链接标记
指示链接器将该函数放置在.init.text区段,在模块插入时方便内核从ko文件指定位置读取入口函数的指令到特定内存位置
2.__exit的作用:展开后为:__attribute__ ((__section__ (".exit.text")))   实际也是gcc的一个特殊链接标记,指示链接器将该函数放置在.exit.text区段,在模块插入时方便内核从ko文件指定位置读取出口函数的指令到另一个特定内存位置;
3.module_init 宏,静态加载模块,内核启动过程中对应函数被调用; 对于静态加载的模块其本质是定义一个全局函数指针,并将其赋值为指定函数,链接时将地址放到特殊区段(.initcall段),方便系统初始化统一调用。对于动态加载的模块,由于内核模块的默认入口函数名是init_module,用该宏可以给对应模块入口函数起别名。
4.用法:module_exit(模块出口函数名)
动态加载的模块在卸载时,对应函数被调用
对于静态加载的模块其本质是定义一个全局函数指针,并将其赋值为指定函数,链接时将地址放到特殊区段(.exitcall段),方便系统必要时统一调用,实际上该宏在静态加载时没有意义,因为静态编译的驱动无法卸载;对于动态加载的模块,由于内核模块的默认出口函数名是cleanup_module,用该宏可以给对应模块出口函数起别名。

内核模块的插入:

1.编译好test.c

2.修改Makefile                              obj-M  +=  test.o

3.make

4.sudo dmesg -C                          不显示 没改动的内核代码             

5.sudo insmod ./test.o

6.dmesg                                     显示新加内核功能信息

7.sudo rmmod test                    移除模块test

内核依赖

既然内核模块的代码与其它内核代码共用统一的运行环境,也就是说模块只是存在形式上独立,运行上其实和内核其它源码是一个整体,它们隶属于同一个程序,因此一个模块或内核其它部分源码应该可以使用另一个模块的一些全局特性。

一个模块中这些可以被其它地方使用的名称被称为导出符号,所有导出符号被填在同一个表中这个表被称为符号表。

最常用的可导出全局特性为全局变量和函数

查看符号表的命令:nm nm查看elf格式的可执行文件或目标文件中包含的符号表,用法:

nm 文件名 (可以通过man nm查看一些字母含义)

两个用于导出模块中符号名称的宏:

EXPORT_SYMBOL(函数名或全局变量名) EXPORT_SYMBOL_GPL(函数名或全局变量名) 需要GPL许可证协议验证

使用导出符号的地方,需要对这些符号进行extern声明后才能使用这些符号

B模块使用了A模块导出的符号,此时称B模块依赖于A模块,则:

  1. 编译次序:先编译模块A,再编译模块B,当两个模块源码在不同目录时,需要:i. 先编译导出符号的模块A ii. 拷贝A模块目录中的Module.symvers到B模块目录 iii. 编译使用符号的模块B。否则编译B模块时有符号未定义错误

  2. 加载次序:先插入A模块,再插入B模块,否则B模块插入失败

  3. 卸载次序:先卸载B模块,在卸载A模块,否则A模块卸载失败

补充说明: 内核符号表(直接当文本文件查看) /proc/kallsyms运行时 /boot/System.map编译后


http://www.kler.cn/a/158570.html

相关文章:

  • 详细分析ipvsadm负载均衡的命令
  • 39.十进制数转化为二进制数 C语言
  • CC工具箱使用指南:【CAD导出界址点Excel】
  • 【MYSQL】锁详解(全局锁、表级锁、行级锁)【快速理解】
  • 已有docker增加端口号,不用重新创建Docker
  • MYSQL_深入理解自连接_图书借阅情况(2/2)
  • Qt 布局讲解及举例
  • 打破界限:SQL数据库水平扩展的8大挑战与机遇
  • 【开源】基于JAVA的医院门诊预约挂号系统
  • (C++)有效三角形的个数--双指针法
  • 推荐6款本周 火火火火 的开源项目
  • SpringBoot学习笔记-实现微服务:匹配系统(下)
  • C语言初学4:C 存储类
  • RocketMQTemplate 发送消息的高级用法
  • 流程编排-java
  • GOLAND搭建GIN框架以及基础框架搭建
  • 一文解决msxml3.dll文件缺失问题,快速修复msxml3.dll
  • postgresql-effective_cache_size参数详解
  • 对小程序的初了解
  • 理解DuLinkList L中的“”引用符号
  • 创建JDK8版本的SpringBoot项目的方法
  • Git 分支详解
  • 【shell】多行重定向与免交互expect与ssh、scp的结合使用
  • vue3 vue-router过渡动效 滚动行为 (四)
  • 使用rust slint开发桌面应用
  • Docker 容器日志查看和清理