恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
device_add源码研究
首页
资讯中心
/
device_add源码研究
device_add源码研究
发布时间:2026/10/10 1:59:50
前面光学习了bus和class的基本结构和注册方法其如何和device产生互动的,什么时候会创建到/sys/devices/下目录的链接等这些问题还需要再探究一下最好的开始就是device_add从device_register开始其负责调用device_initialize()里面设置其暂时属于devices_kset,以及内核管理用的ktype初始化一些必须要用的数据,链表等device_add源码研究第一段1594行内部给device的私有数据申请了空间给device维护了一个klist链表其p指针的私有数据结构体如下通过上面这个结构体,能将device安全的插入到不同的层级结构中,同时还能保留父子设备的拓扑信息1604行-1616行是确定device的名称,也就是确认其内嵌Kobj的名称逻辑是先用指定的名称,没有再通过bus来确定名称第二段1620行,获取当前设备的父设备1621行,里面有点复杂,整体功能是确定当前device的kobj在sysfs层级结构中的位置,需要展开讲讲也就是确定当前device的目录,应该在/sys/devices/下的哪个子目录里面get_device_parent1320行,首先判断该设备是不是一个类设备如果不是类设备,直接看1369行,一般情况下,对于设备注册都会指定父设备,如果没有指定,就看当前bus有没有提供默认父设备,提供了则返回这个默认的/sys/devices/下的父设备作为挂载点1372行,则排除上面这些特殊情况后,如果当前设备有父设备,则正常返回其父设备的kobj,作为sysfs层级结构中当前设备kobj的父亲接下来再看比较复杂的对于类设备找sysfs层级结构中父节点的处理同时我提到的/sys/的目录结构,也就代表了sysfs中kobj的层级结构1339行,首先判断当前类设备有没有父亲,没有的话则调用virtual_device_parent为其创建一个虚拟的父亲,该虚拟父亲直接就在/sys/devices/下存在1341行,如果当前类设备有父亲,并且其父亲也是一个类设备,而且父亲还没有指定命名空间那么就很简单,直接返回当前类设备的父亲的kobj,即他俩是在一个类目录下的父子关系1344行,就是这样一种条件:当前设备既有父设备,而且还归属于某个类此时就暂时先将parent_kobj指针指向父设备的kobj,1349行开始处理这个设备1350行,则开始遍历当前class提供的胶水目录的kobj如果能找到一个胶水目录的parent,就是当前设备的父设备的kobj则直接返回该胶水目录的Kobj所谓胶水目录,就是内核为了让一个既有父设备,又是类设备的设备在/sys/devices层级结构中保持结构清晰,在其父设备的目录下,又加了一个以其所属类命名的目录1362行,这里就是创建胶水目录的地方,说明前面没有给该类设备在其父设备目录下找到胶水目录这里就在其父设备的/sys/devices/目录中的所属位置下,创建一个名为其所属类名称的目录同时,这些胶水目录还挂载在对应的class下的p-glue_dirs.list上这样,通过class可以很方便的找到这些在不同父设备下的同一类的设备而且还通过加了一层胶水目录的方式,完美留存了父子设备的关系整个目录就变成这样/sys/devices/../父设备 -类1 -子设备1 -子设备2 -类2 -子设备3 -子设备41622行,将前面找到的父亲kobj作为当前设备内嵌kobj的父亲1626行,这里是让申请连续内存的位置跟随其父设备的位置,这块又涉及到一个复杂知识点NUMA,反正这里这样操作的原因是为了提高内存访问效率1631行,正式将device的kobj注册进sysfs的层级结构中,并且在/sys/devices下生成对应目录1638行,在设备向统一设备模型注册完成的第一时间通知特定硬件架构平台Platform/Architecture-specific code执行底层的硬件级绑定与钩子处理。这个不同平台的实现方式也不同,也是个比较复杂的内容,有时间再研究1641行,在当前设备对应的/sys/devices/中的目录中创建属性文件1645行,创建其到设备树节点的链接和其到class目录的链接文件 (如果有的话)1648行,添加一些类设备特有的属性1651行,将当前device添加到对应的总线上,作为knode加到其bus的klist上1654,这块没学习过,暂时就是添加一些电源管理的文件,然后加入到对应的pm系统中第三段这段代码很关键,因为有些设备节点是不具备真实读写的能力的,其是作为虚拟纯逻辑节点比如usb的interfaces,虽然其会被加入到sysfs层级结构中,但是其具体提供读写的字符设备却是驱动probe中代码创建出来的这里判断如果某个device已经被分配了设备号,则说明其能被vfs进行路由,也就意味着其能够被作为文件操作这里就直接让devtmpfs给当前device在/dev下创建节点第四段前提,一个device不能既是bus设备,又是class设备,bus负责物理逻辑,class负责使用逻辑整体做的就是通知bus,有新设备添加了,同时发布新Kobj添加的uevent到用户空间然后1679行让bus开始遍历自己的两个klist,进行设备驱动匹配1680行,维持在sysfs体系结构之外的对当前device的拓扑结构,该拓扑结构对用户不可见1684行,如果当前设备是类设备,则将其添加到其类的klist中同时调用监听该类的所有外部模块的class_interface,告知他们有新设备添加进来了对这个class_interface的解释如下:class interfaces:让第三方内核模块能够订阅某个class下的设备添加或者移除的接口,其插入到interfaces链表的结构体如下.其实也很好理解,就是当设备被注册到class上的时候,调用所有的class_interface中的add_dev()函数做第三方模块的对应操作总而言之,就是让别的模块可以添加自己的接口来监听该class类上的设备,当该class有设备被添加或者移除的时候,能够自动调用上面这两个函数,做出一些对应的操作比如evdev模块就添加自己的接口来监听input_class上设备的注册,然后class上设备添加的时候调用interfaces链表中的所有class interface的add_dev()函数,该函数自己再去/dev/input/下创建对应的eventx的inode设备节点