hotplug启动过程之call_usermodehelper分析

来源:互联网 发布:p站下图软件 编辑:程序博客网 时间:2024/05/25 01:35

主题引子:

系统启动后,每次插入或拔出usb设备,应用层会通过进程hotplug来对usb分区做相应的mount或umount操作,且该hotplug进程并非守护进程,执行完操作后即退出,不在会ps中显示出来。 开始以为hotplug进程是被应用层消息框架所触发,即消息总控层收到内核驱动响应事件,然后通过消息机制发送消息启动hotplug进程。为了验证该论断,在消息机制总控层代码中添加打印进行调试,发现一直都没有相应打印,难道hotplug启动过程跟应用层消息机制没有关系,那hotplug又是如何被内核驱动层触发的呢?

由于hotplug可执行二进制文件放在bin目录,在sbin目录也有一个link链接,可以通过bin/hotplug或sbin/hotplug来启动,于是尝试在全局grep搜索bin/hotplug,果然在kernel中找到sbin/hotplug及其对应宏CONFIG_UEVENT_HELPER_PATH,继续搜索宏CONFIG_UEVENT_HELPER_PATH,很快定位到文件kobject_uevent.c中,做进一步分析,找到关键函数call_usermodehelper(),当时还并没有引发自己的重视,仅仅当做一陌生函数去baidu了解下功能,这才发现改函数的厉害所在,该问题的关键所在,就是它被驱动触发并从内核中启动了用户层的hotplug进程。

若在项目中不想使用hotplug,可以在内核配置文件中进行配置,或者在hotplug应用程序代码中注掉相应代码即可。

内核中配置路径:makemenuconfig    Device Drivers   --->  General Driver Options   --->  hotplug

使用usermode-helper API的实现从内核调用或启动用户空间应用程序:

调用特定的内核函数(系统调用)是 GNU/Linux 中软件开发的原本就有的组成部分。但如果方向反过来呢,内核空间调用用户空间?确实有一些有这种特性的应用程序需要每天使用。例如,当内核找到一个设备,这时需要加载某个模块,进程如何处理?动态模块加载在内核通过 usermode-helper 进程进行。

usermode-helper API 中的一些核心函数来实现内核启动用户进程,核心函数提供了最大程度的控制,其中 helper 函数在单个调用中完成了大部分工作。管道相关调用(call_usermodehelper_stdinpipe 和 helper 函数 call_usermodehelper_pipe)创建了一个相联管道供helper 使用。具体地说,创建了管道(内核中的文件结构)。用户空间应用程序对管道可读,内核对管道可写。

最直接的 usermode-helper API 应用程序是从内核空间加载内核模块。request_module 函数封装了 usermode-helper API 的功能并提供了简单的接口。在一个常用的模块中,内核指定一个设备或所需服务并调用 request_module 来加载模块。通过使用 usermode-helper API,模块通过 modprobe 加载到内核(应用程序通过 request_module 在用户空间被调用)。与模块加载类似的应用程序是设备热插拔(在运行时添加或删除设备)。该特性是通过使用 usermode-helper API,调用用户空间的 /sbin/hotplug 工具实现的。

call_usermodehelper()函数是简化了的API函数,执行了核心API函数setup和exec等。

usermode-helperAPI 是内核中重要的部分,这是由于其广泛多样的用途(从内核模块加载、设备热插拔到 udev 事件发布)。尽管 API 实际的应用程序非常重要,但内核也是很重要的一部分,是非常有用的 Linux 工具。


了解更多:

http://blog.sina.com.cn/s/blog_7cd02bea0100pn06.html

0 0