引自帖子
--
谁能说一下当一个设备插入系统后的过程,产生热插拔,udev,NETLINK,中断? 思路很乱,谁能完整说一下流程啊?从插入设备到在/dev下创建设备结点!
比如都说热插拔是在插入设备时产生的,那么这个热插拔是在创建kobject时产生的还是...希望能说一下流程!
--
USB插入,中断,处理,uevent上报事件 kernel部分完毕(驱动版块有参考)
发现有uevent事件,多了个device设备,创建设备节点,使用者user部分完毕,继续等待其他uevent事件这(该程序在嵌入式版块有参考)
--
没有从源码上仔细看,仅凭“臆测”,来说一下个人的理解;
首先要分清角色,这里有:
① 可插拔外设;
② 总线,如usb;
③ sysfs;
④ netlink;
⑤ udev;
⑥ devfs(对应/dev目录);
分下类,
① 外设驱动、总线驱动、sysfs在内核空间;
② udev运行在用户空间,根据/sys目录的变化来在/dev目录下动态创建设备文件;
③ netlink是用户空间和内核空间通信的方式,其他通信方式还有system call, ioctl, proc filesystem;
至于流程,大致如下:
① 外设插入;
② 总线发现(中断?)新设备,并调用总线驱动查找驱动程序;[“Find a driver that can handle the device” =》 “Bind a driver to that device” =》 “Tell other subsystems to configure the new device.”(参见document/usb/hotplug.txt)]
③ 找到合适的驱动后,会调用device_add,添加新设备到设备管理系统;
④ device_add中会调用kobject_uevent(, KOBJ_ADD),向userspace广播新设备加入event通知;这里发出通知的方式,就是netlink;
⑤ 用户空间运行的daemon(udevd ?或者khubd等转发给udevd?)收到event事件广播;
⑥ udevd根据消息和环境变量,查询/sys的变化,在/dev目录下自动创建设备节点;
>比如都说热插拔是在插入设备时产生的,那么这个热插拔是在创建kobject时产生的还是...
热插拔事件有很多种:
- enum kobject_action {
- KOBJ_ADD,
- KOBJ_REMOVE,
- KOBJ_CHANGE,
- KOBJ_MOVE,
- KOBJ_ONLINE,
- KOBJ_OFFLINE,
- KOBJ_MAX
- };
--
>⑤ 用户空间运行的daemon(udevd ?或者khubd等转发给udevd?)收到event事件广播;根据udev(7) manpage:The udev daemon udevd(
receives device uevents
directly from the kernel whenever a device is added or removed
from the system, or it changes its state.
又khubd属于内核线程,运行在内核空间:- wjcdx@lj:/etc/udev/rules.d$ ps aux | grep khubd
- root 29 0.0 0.0 0 0 ? S Nov16 0:00 [khubd]
- wjcdx 3779 0.0 0.3 4016 768 pts/6 S+ 20:05 0:00 grep --color=auto khubd
- wjcdx@lj:/etc/udev/rules.d$
- wjcdx@lj:/etc/udev/rules.d$
- wjcdx@lj:/etc/udev/rules.d$
- wjcdx@lj:/etc/udev/rules.d$ ps aux | grep udev
- root 263 0.0 0.0 2396 172 ? S Nov16 0:00 upstart-udev-bridge --daemon
- root 268 0.0 0.0 2628 144 ? S
- root 390 0.0 0.0 2624 148 ? S< Nov16 0:00 udevd --daemon
- root 407 0.0 0.0 2624 152 ? S< Nov16 0:00 udevd --daemon
- wjcdx 3781 0.0 0.3 4012 768 pts/6 S+ 20:05 0:00 grep --color=auto udev
复制代码 可以看出khubd的进程好是0,而udevd的进程号则不是0;根据中说:在系统初始化的时候在usb_init函数中调用usb_hub_init函数,就进入了hub的初始化。
在usb_hub_init函数中完成了注册hub驱动,并且利用函数kthread_run创建一个内核线程。该线程用来管理监视hub的状态,所有的情况都通过该线程来报告。
可以猜测,khubd内核线程负责向udevd报告usb hub的所有状态改变;证诸内核代码:- int usb_hub_init(void)
- {
- ***
- khubd_task = kthread_run(hub_thread, NULL, "khubd");
- ***
- }
复制代码 hub_thread()->hub_events()->hub_port_connect_change()->usb_new_device()->device_add()->kobject_uevent();
--
Usually, when you run ps -aux and look at the khubd process,
you see that it is sleeping, denoted by the letter S. When we plug a USB device
into the USB port, the hardware layer initiates an interrupt; we reach the hub_irq() method.
The hub data, represented by struct usb_hub, is passed to the hub_irq() method
as part of the URB, the context member of struct urb.
A global list of hub events, called hub_event_list, is available. If
this list is empty, we add an event to this list, so that the khubd thread
can handle it. We also call wake_up(&khubd_wait), as khubd is in waiting status.
Waking up causes us to call hub_events().
From还剩下一个问题,就是如果设备的驱动是在设备插入时动态加载的,那这个加载过程,处在这一个过程的哪一个位置?
--
回复 wangjianchangdx device_add():- kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_probe_device(dev);
复制代码 可以看出是先发出event事件,后为device probe driver;细细想来,udev的功能与驱动没必然关系:udev可以probe driver,也可以不加载,看udev规则高兴;调用udev之前可以有driver,反之亦可;udev的功能,引自udev(7) manpage: udev provides a dynamic device directory containing only the files for actually present devices. It creates or removes device node files in the /dev directory, or it renames network interfaces.
Usually udev runs as udevd(8) and receives uevents directly from the kernel if a device is added or removed from the system.
If udev receives a device event, it matches its configured rules against the available device attributes provided in sysfs to identify the device. Rules that match may provide additional device information or specify a device node name and multiple symlink names and instruct udev to run additional programs as part of the device event handling.
没有明显的说明是否probe driver,但它的主要功能如上面粗体部分,而不是probe driver;没有找到驱动的设备,就不能创建设备文件了吗?答案当然是可以。所以,上面所说的过程可以去除driver部分,简化如下:① 外设插入;② 总线发现(中断? usb有中断hub_irq,pci的中断没找到)新设备,调用device_add,添加新设备到设备管理系统;③ device_add中调用kobject_uevent(, KOBJ_ADD),向userspace广播新设备加入event通知;这里发出通知的方式,就是netlink;④ 用户空间运行的daemon(udevd)收到event事件广播;⑤ udevd根据消息和环境变量,查询/sys的变化,按照规则(/etc/udev/rules.d/*),在/dev目录下自动创建设备节点;以上,多所臆测,还望知者指教!
--
同时可以总结,设备插入系统时,相应驱动的关联情况:
① 若直接编译进内核或在启动时加载,则无需在udev中加载驱动模块,在bus_probe_device()中会为其找到相应的驱动;
② 若驱动需要动态加载,则需要在udev(目前的情况是这样,以前也有其他方式如/sbin/hotplug,cardmgr等)中,动态加载其驱动,在驱动的register函数中,找到该device进行关联;
--
现在的devtmpfs又变回去了,device_add的时只要有major number就会为其生成一个结点。不知道跟udev是怎么配合的。
阅读(8320) | 评论(0) | 转发(8) |