在LDD3的十四章,是Linux设备模型,其中也有说到这个部分。
我的理解是自动在应用层也就是用户空间实现设备管理,处理内核的设备事件。
事件来自sysfs和/sbin/hotplug。在驱动中,只要是使用了新版的函数,相应的事件就会自动发给udev,udev可以创建和删除设备节点。
====================20250118更新====================
1 理论
书里面还是讲得很细,重点就是下面这个图。
然后将了kobject,kset,总线,类,热拔插这些。但是对一个很重要的概念,就是设备模型到底是干嘛的,着墨却不多。这也是我觉得这个书编排不大好的地方。
目前我的理解,设备模型,就是linux 2.6(2003年发布)里面集成的一套标准驱动框架,一套封装而已。你用了这套东西,那么sys里面的管理,热拔插,设备树,ACPI,电源管理,这些封装自动就给你干了,你要省一些事。
先理解这个,至于什么kobject,类,后面可以再慢慢看。
设备模型的核心架构是分层的,主要包括 总线(Bus)、设备(Device)、驱动(Driver) 和 类(Class)。 每一层都实现特定的功能:
总线层:管理设备和驱动的绑定,如 PCI 总线或 USB 总线。
设备层:表示具体的硬件设备,包含设备的基本属性。
驱动层:负责具体设备的操作逻辑。
类层:对功能相似的设备进行分类管理,例如块设备类、字符设备类。
2 实践
代码呢也不是书里说的scullp,而是lddbus。示例代码很简单。
首先还是一个初始化,一个退出。
module_init(ldd_bus_init);
module_exit(ldd_bus_exit);
init也很简单
static int __init ldd_bus_init(void)
{
int ret;
ret = bus_register(&ldd_bus_type);
if (ret) {
printk(KERN_ERR "Unable to register ldd bus, failure was %d\n",ret);
return ret;
}
if (bus_create_file(&ldd_bus_type, &bus_attr_version))
printk(KERN_ERR "Unable to create version attribute\n");
dev_set_name(&ldd_bus,"ldd0");
ret = device_register(&ldd_bus);
if (ret) {
printk(KERN_ERR "Unable to register ldd0, failure was %d\n",ret);
goto out_fail;
}
return 0;
out_fail:
bus_unregister(&ldd_bus_type);
return ret;
}
这里可以看到,传统的驱动是register_chrdev,注册字符设备。而设备模型呢,是用的bus_register和device_register,或者是class_create创建设备类,之后device_create。
卸载也很简单:
static void ldd_bus_exit(void)
{
device_unregister(&ldd_bus);
bus_unregister(&ldd_bus_type);
}
可以看到,就是两个unregister。传统的是直接unregister_chrdev。