udev
the workflow of udev:
- 启动初始化时, /dev目录使用tmpfs挂载.
- 然后, Udev拷贝/lib/udev/devices 的静态设备节点到 /dev 目录.
- Udev守护进程开始运行,为所有连接到系统的设备收集来自内核的uevents.
- Udev守护进程解析uevent数据,并且对/etc/udev/rules.d中指定的规则进行匹配.
- 根据指定的规则为设备创建设备节点和符号链接.
- Udev守护进程读取/etc/udev/rules.d/*.rules 中的规则并且保存到内存里面.
- Udev接收接收inotify事件,如果某个规则发生了改变,读取这些改变并更新内存副本.
udev通过NetLink注册内核的设备事件,当有设备插入/拔除时,udev就会收到通知,它会从事件中所带参数和sysfs中的信息,加载适当的驱动程序,创建dev下的设备节点,使设备处于可用的状态。具体流程如下:
udev通过kernel收到一个uevent,若是移除设备的uevent,则删除/dev中相应的设备文件;若是一个添加设备的uevent,则在配置文件/etc/udev/udev.conf或/lib/udev/udev.conf中查找规则文件所在目录(默认规则目录是:/lib/udev/rules.d/,客户规则目录/etc/udev/rules/(优先级最高), 临时规则目录:/dev/.udev/rules.d/),然后按照顺序遍历所有规则文件,若此设备没有与之匹配的规则,则在/dev中产生一个设备文件,此设备文件以内核设备名称命名;若找到于此设备匹配的规则,则按照规则在/dev下产生相应的设备文件。
dbus
D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和Linux内核事件作为消息传递到进程。D-Bus的主要概率为总线,注册后的进程可通过总线接收或传递消息,进程也可注册后等待内核事件响应,例如等待网络状态的转变或者计算机发出关机指令。目前,D-Bus已被大多数Linux发行版所采用,开发者可使用D-Bus实现各种复杂的进程间通信任务。
D-Bus是一个消息总线系统,其功能已涵盖进程间通信的所有需求,并具备一些特殊的用途。D-Bus是三层架构的进程间通信系统,其中包括:
接口层:接口层由函数库libdbus提供,进程可通过该库使用D-Bus的能力。
总线层:总线层实际上是由D-Bus总线守护进程提供的。它在Linux系统启动时运行,负责进程间的消息路由和传递,其中包括Linux内核和Linux桌面环境的消息传递。
包装层:包装层一系列基于特定应用程序框架的Wrapper库。
总线是D-Bus的进程间通信机制,一个系统中通常存在多条总线,这些总线由D-Bus总线守护进程管理,系统总线(system bus),会话总线(session bus)。
系统总线,Linux内核引导时,该总线就已被装入内存。只有Linux内核、Linux桌面环境和权限较高的程序才能向该总线写入消息,以此保障系统安全性,防止有恶意进程假冒Linux发送消息。
会话总线,由普通进程创建,可同时存在多条。会话总线属于某个进程私有,它用于进程间传递消息。
D-Bus机制的几个重要概念:
对象:对象是封装后的匹配器与回调函数,它以对等(peer-to-peer)协议使每个消息都有一个源地址和一个目的地址。这些地址又称为对象路径,或者称之为总线名称。对象的接口是回调函数,它以类似C++的虚拟函数实现。当一个进程注册到某个总线时,都要创建相应的消息对象。
消息:D-Bus的消息分为信号(signals)、方法调用(method calls)、方法返回(method returns)和错误(errors)。信号是最基本的消息,注册的进程可简单地发送信号到总线上,其他进程通过总线读取消息。方法调用是通过总线传递参数,执行另一个进程接口函数的机制,用于某个进程控制另一个进程。方法返回是注册的进程在收到相关信息后,自动做出反应的机制,由回调函数实现。错误是信号的一种,是注册进程错误处理机制之一。
服务:服务(Services)是进程注册的抽象。进程注册某个地址后,即可获得对应总线的服务。D-Bus提供了服务查询接口,进程可通过该接口查询某个服务是否存在。或者在服务结束时自动收到来自系统的消息。
建立服务的流程:
建立一个dbus连接之后 -- dbus_bus_get(),为这个dbus连接(DbusConnection)起名 -- dbus_bus_request_name(),这个名字将会成为我们在后续进行远程调用的时候的服务名,然后我们进入监听循环 -- dbus_connection_read_write()。在循环中,我们从总线上取出消息 -- dbus_connection_pop_message(),并通过比对消息中的方法接口名和方法名 -- dbus_message_is_method_call(),如果一致,那么我们跳转到相应的处理中去。在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路 -- reply_to_method_call()。回传动作本身等同于一次不需要等待结果的远程调用。
发送信号的流程:
建立一个dbus连接之后,为这个dbus连接起名,建立一个发送信号的通道,注意,在建立通道的函数中,需要我们填写该信号的接口名和信号名 -- dbus_message_new_signal()。然后我们把信号对应的相关参数压进去 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic()。然后就可以启动发送了 -- dbus_connection_send(); dbus_connection_flush。
进行一次远程调用的流程:
建立好dbus连接之后,为这dbus连接命名,申请一个远程调用通道 -- dbus_message_new_method_call(),注意,在申请远程调用通道的时候,需要填写服务器名,本次调用的接口名,和本次调用名 (方法名)。压入本次调用的参数 -- dbus_message_iter_init_append(); dbus_message_iter_append_basic(),实际上是申请了一个首地址,我们就是把我们真正要传的参数,往这个首地址里面送(送完之后一般都会判断是否内存越界了)。然后就是启动发送调用并释放发送相关的消息结构 -- dbus_connection_send_with_reply()。这个启动函数中带有一个句柄。我们马上会阻塞等待这个句柄给我们带回总线上回传的消息。当这个句柄回传消息之后,我们从消息结构中分离出参数。用dbus提供的函数提取参数的类型和参数 -- dbus_message_iter_init(); dbus_message_iter_next(); dbus_message_iter_get_arg_type(); dbus_message_iter_get_basic()。也就达成了我们进行本次远程调用的目的了。
信号接收流程:
建立一个dbus连接之后,为这个dbus连接起名,为我们将要进行的消息循环添加匹配条件(就是通过信号名和信号接口名来进行匹配控制的) -- dbus_bus_add_match()。我们进入等待循环后,只需要对信号名,信号接口名进行判断就可以分别处理各种信号了。在各个处理分支上。我们可以分离出消息中的参数。对参数类型进行判断和其他的处理。http://www.cnblogs.com/wzh206/archive/2010/05/13/1734910.html
udisks
udisks是一个定义良好的dbus接口,它枚举块设备并对块设备执行相应的操作。任何应用程序可以通过系统消息总线访问org.freedesktop.UDisks。
udisks守护程序提供基于系统消息总线的org.freedesktop.UDisks服务。用户或管理员不需要启动这个守护进程,当一个应用程序访问org.freedesktop.UDisks服务启动dbus的守护进程时udisks-daemon将自动启动。
http://hal.freedesktop.org/docs/udisks/UDisks.html
来源:CSDN
作者:fengying765
链接:https://blog.csdn.net/fengying765/article/details/6996415