内核驱动的本质——模块

2023-05-16

内核驱动的本质——模块

在Linux中,驱动的本质就是一个模块。模块可以被选择“静态编译”或“模块化编译”
1. 静态编译:链接入内核镜像,默认永远被加载
2. 模块化编译:需要在内核运行时动态加载
这两种处理步骤详见驱动模块的编译与安装
当模块被加载时,可以认为模块即是内核的一部分

1.一个最简单的模块

#include <linux/module.h>   
#include <linux/init.h> 

static int var = 666;
module_param(var, int, S_IRUGO);

/*
 * 用户定义的加载、卸载函数,需要与加载、卸载行为绑定
 */
static int __init chrdev_init(void)
{   
    printk(KERN_INFO "chrdev init\n");
    return 0;
}

static void __exit chrdev_exit(void)
{
    printk(KERN_INFO "chrdev exit\n");
}

module_init(chrdev_init);
module_exit(chrdev_exit);

/*
 * 模块描述信息
 */
MODULE_LICENSE("GPL");              
MODULE_AUTHOR("taurenking");                
MODULE_DESCRIPTION("test"); 
MODULE_ALIAS("xxx");            

2. 用户定义加载、卸载函数

static int __init chrdev_init(void)//自定义的加载函数
{   
    printk(KERN_INFO "chrdev init\n");
    return 0;
}

static void __exit chrdev_exit(void)//自定义的卸载函数
{
    printk(KERN_INFO "chrdev exit\n");
}

module_init(chrdev_init);//将加载、卸载行为绑定
module_exit(chrdev_exit);
  • 当模块被加载、卸载时,会分别执行用户绑定过的加载、卸载函数。加载函数需要完成模块的初始化工作;而卸载函数则完成相反的功能,加载函数申请了什么,卸载函数就要释放什么
  • 关于__init和__exit标识,__init实质是一个宏:
    #define _ _init _ _attribute_ _ ((_ _section_ _ (".init.text")))
    其作用就是将被他修饰的函数链接入.init.text段(本来默认是代码段)。内核中所有这类函数都会被链接入.init.text段中,故所有模块的加载函数其实是被统一存放的。内核启动时统一会加载.init.text段中的这些模块加载函数,加载完后就会把这个段给释放掉以节省内存。__exit标识同理
  • 加载和卸载函数需要使用module_init()和module_exit()来与加载、卸载行为绑定;module_init()和module_exit()的实质是带参宏,它们会把加载、卸载函数指针传给内核来进行绑定

3.模块描述信息

MODULE_LICENSE("GPL");//描述模块的许可证                
MODULE_AUTHOR("taurenking");//描述模块的作者               
MODULE_DESCRIPTION("test");//描述模块的介绍信息  
MODULE_ALIAS("xxx");//描述模块的别名信息         
  • 模块描述信息没什么特别的,唯一值得注意的是许可证,一般都为“GPL”,否则可能会出错

4.模块传参

  • 我们可以在模块内以全局变量的形式定义参数,使用module_param()来告诉kernel这个全局变量是参数。其中第一个参数是变量名,第二个参数是类型,第三个参数是读写权限
static int var = 666;
module_param(var, int, S_IRUGO);
  • 以本文的模块为例,用户层可以使用insmod test.ko var=123来传参,当用户选择不传参时,则以模块内部参数的默认值作为参数值
  • 那么对于静态链接进内核的模块,如何传参呢?可以在U-boot中的bootargs里设置test.ko.var=123来传参,这种情况说实话很少见。。。。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内核驱动的本质——模块 的相关文章

  • 安装Mavlink generator出现UnicodeEncodeError错误

    最近在看mavlink 在执行官网的操作时出现了问题 问题如下 span class hljs constant Exception span span class hljs keyword in span span class hljs
  • mc_att_control基础知识:向量运算和罗德里格斯旋转

    向量的叉乘和点乘 在我们的mc att control中有我们的向量的点乘和叉乘 一般遇到的都是三维的运算 S O 3 S O 3 李群 向量点乘 假设向量 a 61 a 1 a 2 a 3
  • 低通滤波器和高通滤波器的程序实现原理推导

    傅立叶变换 拉普拉斯变换和Z变换 对于信号分析而言 傅立叶变换是必不可少的 我们都知道傅立叶变换是把系统从时域变换到频域进行分析 那么拉普拉斯变换和Z变换是干什么的 简单的来说 由于傅里叶变换的收敛有一个狄利克雷条件 xff0c 要求信号绝
  • PX4源码解读之fw_pos_control_l1

    固定翼的位置控制是一个很重要问题 它不同于旋翼的控制 需要对速度和高度进行解耦控制 并且其不能像旋翼那样进行悬停 其转弯的时候有一个转弯半径 本博客不会对源码进行详细的解读 主要是分享一些自己读源码时的资料 自己读的过程中也有注释 想要的同
  • 四元数表示旋转的理解

    哈密尔顿 为了纪念四元数的发明者哈密尔顿 爱尔兰于1943年11月15日发行了下面这张邮票 哈密尔顿简直是个天才 哈密尔顿从小到进入大学之前没有进过学校读书 xff0c 他的教育是靠叔父传授以及自学 他找到了法国数学家克莱罗 xff08 C
  • mc_att_control源码解析

    目录 源码分析内环控制外环控制 之前写了博客分析了一下旋翼姿态控制的基础知识 mc att control基础知识 这次就对照代码将整个旋翼姿态控制过程呈现一遍 先看一下整个程序的框图 从图中可以看到 实际上整个控制分成内外两个环进行控制
  • PX4下载指定版本代码和刷固件的三种方式

    由于之前下载的是1 7版本的代码 现在v5版本的px4需要最新的代码固件 因此这里记录一下 查看自己代码版本 查看自己仓库代码版本的命令如下 git describe always tags 输出 v1 7 0 rc3 9 g0e1c7eb
  • Python怎么调用matlab的

    文章目录 环境的安装安装合适的python环境安装用于 Python 的 MATLAB 引擎 API 环境的安装 安装合适的python环境 研究这个也是在知乎上突然看到的 xff0c 以前python写的多 xff0c 现在由于工作需要
  • insert语句中sequence的使用方法

    我们常常在表中需要插入一些自动增长的值 一方面 我们可以手动添加这些值 xff0c 另一方面 oracle提供的sequence可以帮助我们实现插入的值自动增长 而不需要我们手动的提供值 我们需要做的就是设置好sequence的初值和增长值
  • Ubuntu 安装 vnc server

    查看Ubuntu系统版本 xff1a sudo lsb release a 安装Xfce桌面环境 xff1a sudo apt install xfce4 xfce4 goodies 配置gnome桌面环境 xff0c 参考 xff1a h
  • 嵌入式Linux(4):应用层和内核层数据传输

    文章目录 简介1 如果在应用层使用系统IO对设备节点进行打开 xff0c 关闭 xff0c 读写等操作会发生什么呢 xff1f 写个例子2 假如驱动层的file operations里面没有实现read之类的操作函数 xff0c 会发生什么
  • 嵌入式Linux(5):物理地址到虚拟地址映射

    文章目录 理论知识1 使能了MMU以后有什么好处呢 xff1f 2 MMU非常复杂 xff0c 那么我们如何完成物理地址到虚拟地址的转换呢 xff1f 3 如何查看哪些物理地址被映射过了呢 xff1f 实例 RK3568 理论知识 在Lin
  • 嵌入式Linux(6):驱动模块传参

    文章目录 1 什么是驱动传参 xff1f 2 驱动传参有什么作用 xff1f 3 怎么给我们的驱动传参数 xff1f 传递普通参数传递数组 1 什么是驱动传参 xff1f 驱动传参就是在安装驱动模块 xff08 ko文件 xff09 的时候
  • 嵌入式Linux(7):字符设备驱动--申请设备号

    文章目录 1 字符设备和杂项设备的区别2 注册字符类设备号的两个办法第一种 xff1a 静态分配一个设备号第二种 xff1a 动态分配注销设备号 写代码不带参数测试 xff08 动态分配 xff09 xff1a 带参数测试 xff08 静态
  • 嵌入式Linux(8):字符设备驱动--注册字符类设备

    文章目录 前言上代码 前言 杂项设备 注册杂项设备 xff1a span class token function misc register span span class token punctuation span span clas
  • 嵌入式Linux(9):字符设备驱动--自动创建设备节点

    文章目录 前言1 怎么自动创建一个设备节点 xff1f 2 什么是mdev3 什么是udev 4 怎么自动创建设备节点 xff1f 5 创建和删除类函数 自动生成类代码 6 创建设备函数 自动生成节点代码 前言 在上一节中 xff0c 使用
  • 嵌入式Linux(10):杂项设备和字符设备驱动总结

    文章目录 杂项设备驱动框架图 xff1a 字符设备驱动框架图 xff1a 相对来说 xff0c 如果是操作几个GPIO的操作 xff0c 其实使用简单的杂项设备驱动就可以了 xff0c 字符驱动相对会复杂一点
  • 嵌入式Linux:FrameBuffer 和 DRM/KMS(一)

    文章目录 前言 Linux 的两种显示方案FrameBufferDRM1 GEM2 KMS 参考 xff1a RK3399 探索之旅 Display 子系统 基础概念 参考 xff1a DRM架构介绍 xff08 一 xff09 前言 Li
  • 【RP-RV1126】Ubuntu上配置Buildroot Qt 开发板远程开发调试环境(SSH)

    文章目录 一 前提二 基础设置建设Buildroot编译Qt5配置SSHBuildroot文件系统添加账号密码开发板联网Buildroot文件系统构建时打开rsync功能 三 QtCreator配置3 1 配置Qt交叉编译套件 Kits 配
  • oracle create view语法

    视图实际上是一个或多个表上的预定义查询 xff0c 这些表称为基表 视图并不存储数据 xff0c 只是在查询视图时才访问基表 视图的优点 xff1a 限制用户只能通过视图检索数据 xff0c 对用户屏蔽基表 可以将复杂的查询编写为视图 xf

随机推荐