【Linux源码阅读】Linux 内核module_xxx_driver宏_module_spi_driver-程序员宅基地

技术标签: Linux驱动编程  kernel  linux驱动  

  在阅读其他人编写的Linux驱动源码发现,最后驱动注册和注销时并未使用传统的“module_init”和“module_exit”,而是使用一个宏“module_xxx_driver”代替,如module_i2c_driver、module_spi_driver、module_platform_driver等等。


  Linux驱动程序模型是“总线驱动”+“设备驱动”,比如i2c总线和i2c设备,spi总线和spi设备。“module_xxx_driver”用于编写设备驱动程序调用,分析内核源码可知,其封装了设备的注册和注销函数定义及向内核注册该函数的功能。


module_i2c_driver

  以i2c总线为例。其函数宏名称为“module_i2c_driver”,原型位于“kernel/include/linux/i2c.h”中。

/**
 * module_i2c_driver() - Helper macro for registering a I2C driver
 * @__i2c_driver: i2c_driver struct
 *
 * Helper macro for I2C drivers which do not do anything special in module
 * init/exit. This eliminates a lot of boilerplate. Each module may only
 * use this macro once, and calling it replaces module_init() and module_exit()
 */
#define module_i2c_driver(__i2c_driver) \
	module_driver(__i2c_driver, i2c_add_driver, \
			i2c_del_driver)

  “module_driver”也是一个宏,传入了i2c设备驱动注册和注销函数,宏原型位于“kernel/linux/device.h”中。

/**
 * module_driver() - Helper macro for drivers that don't do anything
 * special in module init/exit. This eliminates a lot of boilerplate.
 * Each module may only use this macro once, and calling it replaces
 * module_init() and module_exit().
 *
 * @__driver: driver name
 * @__register: register function for this driver type
 * @__unregister: unregister function for this driver type
 * @...: Additional arguments to be passed to __register and __unregister.
 *
 * Use this macro to construct bus specific macros for registering
 * drivers, and do not use it on its own.
 */
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

注:
在宏定义define中
##:表示连接意思,如A##B—>AB
##_VA_ARGS_:可变参数宏,函数支持不定长参数

  假设驱动程序调用函数宏原型为:

module_i2c_driver(bmp180_driver);

  根据上述源码预编译后宏展开最终为:

static int __init bmp180_driver_init(void) 
{
     
     i2c_add_driver(&bmp180_driver);
     return 0; 
} 
  
static void __exit bmp180_driver_exit(void) 
{
     
     i2c_del_driver(&bmp180_driver);
} 
module_init(bmp180_driver_init); 
module_exit(bmp180_driver_exit); 

  这 恰恰是以往我们编写驱动时最后的设备注册和注销步骤。因此,我们可以直接调用“module_xxx_driver”实现设备注册、注销函数的定义及向内核注册。


  同理,spi、platform等总线也提供类似的实现宏。

spi:
module_spi_driver	 #/kernel/include/linux/spi/spi.h

platform:
module_platform_driver	 #/kernel/include/linux/platform_device.h
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_20553613/article/details/103789594

智能推荐

http 500内部服务器错误-程序员宅基地

文章浏览阅读2.7k次。http 500内部服务器错误--------------------------------------------------------------------------------一.错误表现 iis5的http 500内部服务器错误是我们经常碰到的错误之一,它的主要错误表现就是asp程序不能浏览但htm静态网页不受影响。另外当错误发生时,系统事件日志和安全事件日志都会有..._http500

Oracle Temp临时表空间及其故障处理-程序员宅基地

文章浏览阅读575次。Oracle Temp临时表空间及其故障处理 Oracle 11g中Temp临时表空间、文件的新特性 临时表空间是Oracle体系结构中比较特殊的结构。通常情境下,数据库..._ora临时表空间报错,无法打开文件

BurpSuite抓取App包,详细教程_burp抓取手机app数据包-程序员宅基地

文章浏览阅读5.4k次,点赞5次,收藏27次。进入burpsuite工具,配置代理,端口与夜神模拟器保持一致,地址选择指定地址,输入本机IPV4地址;打开burp suite工具进入Proxy,如图,点击open browser。代理选择手动,代理服务器主机名输入本机的IPV4地址(使用。查询),代理服务器端口随便输入,只要不冲突即可;输入证书名,确定,安装成功!_burp抓取手机app数据包

JAVA学习:JAVA中一些常用的方法和使用技巧_java的妙用方法-程序员宅基地

文章浏览阅读401次。目录一、修改数据结构中的Compare二、向二维数组中快速填充同一个元素:三、StringBuilder的常用方法:四、Math的常用方法:参考链接菜鸟教程五、字符串六、容器类一、修改数据结构中的CompareComparable和Comparator的区别:[https://blog.csdn.net/qq_37768971/article/detai..._java的妙用方法

【特征工程】(一)数据集中缺失值的处理_特征工程 空值处理-程序员宅基地

文章浏览阅读9k次,点赞7次,收藏53次。目录引言一、可选处理方法二、Python中Pandas库处理缺失值1.查看数据缺失值得分布情况2.删除包含缺失值的数据 2.1. 删除包含缺失值的行或列 2.2. 根据条件删除包含缺失值的数据三、Python中其他库处理缺失值四、缺失值处理案例(一)----疝气病数据集预处理1.处理缺失值,以便使用分类算法引言 数据中的缺失值是..._特征工程 空值处理

Log4j.properties配置详解-程序员宅基地

文章浏览阅读2.8w次,点赞16次,收藏92次。1 入门示例1.1 新建一个Java工程,导入包log4j-1.2.17.jar,整个工程最终目录如下1.2 src同级创建并设置log4j.properties### 设置###log4j.rootLogger = debug,stdout,D,E### 输出信息到控制抬 ###log4j.appender.stdout = org.apache.log4j.Conso..._log4j.properties

随便推点

python能制作游戏吗_python制作galgame引擎(一)-程序员宅基地

文章浏览阅读654次。写这个项目的直接原因是最近推galgame推得有点过头,gal推过头的直接结果就是YY能力上涨,抱着“我也想写好玩的剧本”的轻率念头,也就开始了这个项目。不过从直接感觉来说,galgame毕竟也是开发成本(个人)以及技术要求最低的游戏类别之一,这当然也算是原因。于是到了现在,一个半成品式的框架就搭好了。实话实说,gal引擎开发,技术难度不算大。但是,需要考虑的方面却相当多,许多看起来很简单的东西开..._galgame的代码很难写吗

高效开发iOS系列 -- 为Xcode添加删除行、复制行快捷键_ios 修改复制粘贴快捷键-程序员宅基地

文章浏览阅读1.4w次,点赞9次,收藏11次。在使用eclipse过程中,特喜欢删除一行和复制一行的的快捷键。而恰巧Xcode不支持这两个快捷键,再一次的恰巧让笔者发现了一个小窍门来增加这两个快捷键,以下是步骤: 修改权限 修改Xcode里快捷键的配置文件(plist)权限,打开终端输入如下两条命令:sudo chmod 666 /Applications/Xcode.app/Contents/Frameworks/IDEKit.fram_ios 修改复制粘贴快捷键

GCC各种调试工具使用简介-程序员宅基地

文章浏览阅读1.7k次。http://blog.sina.com.cn/s/blog_6b94d5680101p7fm.htmlGCC:GNU开发的程序编译器 GNU:“GNU‘s Not Unix”,最初是为了实现一个类似unix的自由操作系统,感觉现在已经通常泛指遵循GPL自由软件精神的组织。GPL:GNU通用公共许可证(GNU General Public License),简单的说就是遵循GPL的

python+selenium简单操作高德地图路线规划_selenium地图-程序员宅基地

文章浏览阅读716次,点赞2次,收藏2次。1、导入selenium库,第三方库要下载pip install selenium_selenium地图

Android 非常简单的实现 Fragment状态栏一体化布局,状态栏字体的颜色改变,_android immersionbar设置黑色字体-程序员宅基地

文章浏览阅读3.4k次。做一个点上的项目的时候遇到一个问题,就是商城首页的布局要覆盖状态栏,可以这么理解,上图:就像京东的首页一样的效果我的项目是 MainActivity + 四个Fragment,第一步:需要把状态栏的背景色变为透明色,这个网上很多博客都写过,我就不写了第二部:我先说一下这个属性fitSystemWindows,因为不管是做状态栏变色和一体化布局,都相关这个属性_android immersionbar设置黑色字体

oracle 传递table,ORACLE 自定义TABLE类型,C#怎么传递值-程序员宅基地

文章浏览阅读137次。该楼层疑似违规已被系统折叠隐藏此楼查看此楼CREATE OR REPLACE TYPE IM_CHECKLIST_PARAM IS OBJECT(ID RAW(16),SCORE INTEGER,DESCRIPTION NVARCHAR2(300),FOLLOWPLAN NVARCHAR2(300));CREATE OR REPLACE TYPE IM_CHECKLIST_T..._oracle自定义数据类型的数据怎么传到procedure c#