Linux驱动开发MODULE_DEVICE_TABLE的作用

作用

MODULE_DEVICE_TABLE宏是用于驱动模块方式开发时会用到的,它的工作原理就是定义驱动的设备ID匹配表,也可以理解为将驱动ID插入到内核匹配表中,它实现的方法就是为当前驱动的设备ID定义一个别名然后insmod命令在加载驱动时会读取这个别名并遍历DTS的compatible是否存在这个设备如果存在则调用init函数,使用别名的原因是因为驱动里变量名称不固定,Linux不可能去规定开发者们变量该用什么名字或者函数该用什么名字,但可以使用一个固定别名指向它

实现原理

kernel/include/linux/module.h文件大约212行可以找到它的实现:

c 复制代码
#ifdef MODULE
/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name)					\
extern typeof(name) __mod_##type##__##name##_device_table		\
  __attribute__ ((unused, alias(__stringify(name))))
#else  /* !MODULE */
#define MODULE_DEVICE_TABLE(type, name)
#endif

它会去判断当前是MODULE方式还是静态编译,如果是静态编译到内核里那它就是一个空函数宏,编译到内核里的话将会通过driver namebusid_table的方式来匹配,id_tableMODULE_DEVICE_TABLE的方式一致,只不过一个是模块的方式一个是内核匹配的方式。

它的实现方式也非常简单,就是利用了GCC的属性,在Linux里你可以看到大量与GCC相关的语法特性,不然怎么叫GNU/Linux呢,背靠GNU Tools,其关键语句是这一行extern typeof(name) __mod_##type##__##name##_device_table __attribute__ ((unused, alias(__stringify(name)))),它定义了一个名为 __mod_##type##__##name##_device_table的变量,然后使用了GCCalias属性定义了一个别名:__attribute__ ((unused, alias(__stringify(name))))unused是指这个变量没有使用也不要报警告而__stringify是将宏转化为字符串,与宏#符号作用一致,这样__mod_##type##__##name##_device_table这个变量就与传递进来的变量关联起来了,__mod_##type##__##name##_device_table就相当于是传递来变量的别名,对它的访问都将指向传递进来的变量。

export在这里的用处是将符号导出可见,在GCC在构建时会有符号表,除了基本的C语言内存布局堆栈BSSDATA段等还有符号表,符号表里存放着符号名称以及地址,全局变量默认是不会被记录在符号表的,如果使用export将符号导出那么它就全局可见,将会被记录在符号表里export除了能够将一个非静态全局变量声明出来使用以外还会将其记录在符号表里这样可以被其它程序在运行期间通过符号表查询对应的地址。这样insmod在加载模块时就可以通过检索__mod_*作为前缀来检索想要的数据并进行匹配了。typeof(name)的作用就是为了匹配不同的类型,Linux里不固定设备ID的类型,但大多数都是用of_device_id,当然也有i2c_device_id...,但它们内存布局是一样的,所以可以通过类型转换来访问接口。

Tips

在module_init里也用了同样的方法,但它没有使用export,除了static函数以外任何函数都会被放入符号表

相关推荐
憧憬一下1 天前
PCIe_Host驱动分析_地址映射
arm开发·嵌入式硬件·嵌入式·linux驱动开发·pci/pcie
憧憬一下9 天前
PCIe的三种路由方式
arm开发·嵌入式硬件·嵌入式·linux驱动开发·pci/pcie
憧憬一下11 天前
深入解析PCIe设备事务层与配置过程
arm开发·嵌入式硬件·嵌入式·pcie·linux驱动开发
憧憬一下18 天前
Linux内核早期打印机制与RS485通信技术
arm开发·嵌入式硬件·嵌入式·linux驱动开发
憧憬一下1 个月前
IMX 平台UART驱动情景分析:read篇--从硬件驱动到行规程的全链路剖析
arm开发·嵌入式硬件·嵌入式·linux驱动开发
憧憬一下1 个月前
UART硬件介绍
arm开发·嵌入式硬件·串口·嵌入式·linux驱动开发
憧憬一下1 个月前
Linux 内核中断描述符 (irq_desc) 的初始化与动态分配机制详解
arm开发·嵌入式硬件·嵌入式·c/c++·linux驱动开发
憧憬一下2 个月前
Pinctrl子系统中Pincontroller和client驱动程序的编写
arm开发·嵌入式·c/c++·linux驱动开发
憧憬一下2 个月前
input子系统的框架和重要数据结构详解
arm开发·嵌入式·c/c++·1024程序员节·linux驱动开发
憧憬一下2 个月前
input子系统中读取流程解析
arm开发·嵌入式·c/c++·linux驱动开发