Udev 内核机制(kobject_uevent) 性能优化

本文详细解析了udev机制,特别是kobject_uevent_env函数的工作流程,并提出了针对内核调用性能的优化方案。
AI助手已提取文章相关产品:

前言

这两天遇到一些udev的问题, 顺便阅读了一下文档(见参考文档), 基本了解了udev的机制。嵌入式系统性能很重要,于是对内核这一块进行了性能方面的研究。

内核大概20多处会调用了kobject_uevent函数发送KOBJ_ADD / KOBJ_REMOVE等事件。其中我们最关心的就是在device_add/device_del中向用户空间发送设备的添加、删除信息。

kobject_uevent直接调用kobject_uevent_env函数完成功能, 我们先分析一下该函数的流程。

kobject_uevent_env调用流程 (内核版本2.6.21

  1. kobject_uevent_env首先搜索kobject所属的kset,获得kset->uevent_ops,类型为kset_uevent_ops(系统一共有block_uevent_opsmemory_uevent_opsdevice_uevent_opsclass_uevent_opsmodule_uevent_ops)这几大类kset_uevent_ops,我们这里主要看device_uevent_ops。
  2. 如果uevent_ops有filter成员函数, 则调用该函数, 如果filter函数返回非0, 则失败,结束流程。device_uevent_ops的filter函数为dev_uevent_filter,它的过滤条件为该设备的总线(bus)或者类(class)非空。
  3. 为envp分配一个大小为 32 的数组,用于存储环境变量指针,为buffer分配一个大小为2048的数组,用于存储环境变量内容。
  4. 初始化环境变量, 包括HOME PATHACTIONDEVPATH SUBSYSTEM等
  5. 如果uevent_ops有uevent函数,则调用该函数, 如果uevent函数返回非0, 则失败,结束流程。device_uevent_ops的uevent函数为dev_uevent,它的流程为:
    1. 添加主次设备号到环境变量
    2. 添加driver的名称到环境变量
    3. 如果设备所属总线(dev->bus)有uevent函数, 则调用它。如失败,结束流程
    4. 如果设备所属类(dev->class)有uevent函数, 则调用它。如失败,结束流程。 (象函数_request_firmware ()中,有两次调用kobject_uevent函数,其中第一次在class的uevent函数firmware_uevent中,测试FW_STATUS_READY位失败而返回)。
    5. 如果设备所属类型(dev->type)有uevent函数, 则调用它。如失败,结束流程. (搜索了一下, 这个field在整个内核里基本没有使用)
    6. 注意每个uevent函数都有机会添加环境变量以及出错返回,结束uevent传递。
  6. 递增uevent序列号uevent_seqnum(可以通过cat /sys/kernel/uevent_seqnum查看)。
  7. 如果定义了CONFIG_NET通过netlink将事件以及环境变量发送出去。
  8. 如果uevent_helper非空, 则调用该函数。uevent_helper的缺省值为:"/sbin/hotplug"应该在用户层调用:echo "" > /sys/kernel/uevent_helper来取消该此调用。

性能数据统计

我们通过高精度定时器(一个3.25M的timer)来统计kobject_uevent的时间花费:

  1. 还没有进入用户空间时,内核调用了kobject_uevent 244次, 平均每次289us,总共70ms(由于每次需要调用并不存在的/sbin/hotplug,时间比较长。
  2. 进入用户空间后,调用udevtrigger,开始15次kobject_uevent调用平均每次6249us,总共93ms(很奇怪,需要深入研究一下)。
  3. 然后181次kobject_uevent调用平均每次47us,总共8ms。

优化方案:

考虑到:

  1. 还没有进入用户空间时发出的uevent看似丢失了!可以不发出
  2. /sbin/hotplug在使用netlink时永远没有必要调用!可以删除

我们可以:

  1. 删除调用/sbin/hotplug的代码
  2. 在uevent_helper非空时不真正发出uevent

这样,在进入用户空间之前,我们的uevent机制不会做任何事情,只有用户空间调用

echo "" > /sys/kernel/uevent_helper

后,uevent才会被真正发送到netlink.

实践证明系统运行良好。

udev参考文档

Writing udev rules

http://reactivated.net/writing_udev_rules.html

udev文件系统的使用和基本工作原理分析

http://blog.youkuaiyun.com/colorant/archive/2008/01/09/2031721.aspx

udev的实现原理

http://blog.youkuaiyun.com/absurd/archive/2007/04/27/1587938.aspx

您可能感兴趣的与本文相关内容

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值