//定义在linux/module.h
//@type:设备类型
//@name:驱动所支持的设备列表。这个设备表的最后一个元素是空的,用于表示结束。
#define MODULE_DEVICE_TABLE(type, name)
extern typeof(name) __mod_##type##__##name##_device_table
__attribute__ ((unused, alias(__stringify(name))))
//在分析内核时,有些函数会添加__attribute__ ((unused))
//这个表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息
__attribute__ ((unused))
1.功能
创建一个指向设备列表name(如hid_device_id)的局部变量(如__mod_hid_device_table)。内核构建的时候,depmod程序会在所有模块中搜索symbol如_mod_hid_device_table,如果搜索到,把数据(设备列表)从模块中抽出,添加到映射文件(如/lib/modules/KERNEL_VERSION/modules.hidmap)中,当depmod结束之后,所有的hid设备连同他们的模块名字都被该文件列出。当内核告知热插拔系统一个新的hid设备被发现,热插拔系统使用modules.hidmap匹配设备信息如PID、VID来寻找恰当的驱动程序。如果匹配到则使用对应的驱动操作此设备,若此时驱动未添加,系统会自动添加(insmod/modprobe)此驱动。
也就是说MODULE_DEVICE_TABLE具有两个功能:
一:将设备加入到外设队列中;
二:告诉程序阅读者该设备是热插拔设备或者说该设备具备热插拔功能。
2.实现
1.定义一个设备列表,例如hid_device_id;
2.调用MODULE_DEVICE_TABLE宏创建一个指向设备列表的变量(因为depmod程序识别的是MODULE_DEVICE_TABLE宏创建出来的type##device_id格式的变量。
3.内核构建过程(启动过程),自动调用depmod程序查找。调用depmod查找是每个内核自动加载模块都经历的,所以每个驱动模块支持的设备列表就会通过type##_device_id被查找到,并在映射文件中列出设备以及驱动的名字。
4.热插拔事件会唤醒热插拔处理程序,热插拔处理程序会到/lib/modules/KERNEL_VERSION/下查找对应的文件,判断设备列表里面的数据与设备是匹配的,匹配则选择该驱动程序。
例如:
当一个设备接到集线器,热插拔系统就被唤醒,hid子系统就会检查插入设备的vendor id 和product id。
//inlude/mod_devicetable.h
struct hid_device_id {
__u16 bus;
__u16 group;
__u32 vendor;
__u32 product;
kernel_ulong_t driver_data;
}
//hid-generic
static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
};
MODULE_DEVICE_TABLE(hid, hid table);
3.热插拔
MODULE_DEVICE_TABLE一般用于动态加载驱动也就是热插拔的时候使用。
模块所支持的热插拔设备信息使用modinfo命令查看,如下:
# modinfo hid-generic.ko | grep "alias" (查看模块支持的热插拔设备)
alias: hid:b*g*v0000xxxxp0000xxxx
# modinfo hid-generic.ko | head -n 50 (查看模块信息)
这些alias存储在模块文件本身(hid-generic.ko)中。modinfo将他们打印出来,depmod将他们写到/lib/modules/VERISON/modules.aliases供modprobe读取,它不会在任何配置文件中读取。
4.模块常用命令
1.insmod xxx.ko //将模块加进内核
2.rmmod xxx.ko //将模块从内核中卸载
3.lsmod //查看已经安装到内核的模块
4.modprobe //载入指定的模块,或是载入一组相互依赖的模块,modprobe会根据depmod锁产生的依赖关系, //决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。依赖关系是通过
//读取/lib/modules/2.6.xx/modules.dep得到的。该文件是depmod建立的。
5.modinfo xxx.ko //读取模块信息。
6.tree -a //查看当前目录的整个树结构