Linux设备模型浅析之uevent篇

合集下载

Linuxexpect详解

Linuxexpect详解

Linuxexpect详解场景现在有两台Linux主机A和B,如何从A主机ssh到B主机,然后在B主机上执⾏命令,如何使这个过程实现全程⾃动化?你可能会使⽤这种⽅法:ssh admin@10.220.20.15 "ls"但是这种⽅式⽐较笨拙,每次都要输⼊密码,同时并不能执⾏⼀些复杂的逻辑或命令。

那么如何实现全程⾃动化呢?这就要⽤到今天这篇⽂章总结的expect了。

expect是什么?expect是⼀个免费的编程⼯具,⽤来实现⾃动的交互式任务,⽽⽆需⼈为⼲预。

说⽩了,expect就是⼀套⽤来实现⾃动交互功能的软件。

在实际⼯作中,我们运⾏命令、脚本或程序时,这些命令、脚本或程序都需要从终端输⼊某些继续运⾏的指令,⽽这些输⼊都需要⼈为的⼿⼯进⾏。

⽽利⽤expect,则可以根据程序的提⽰,模拟标准输⼊提供给程序,从⽽实现⾃动化交互执⾏。

这就是expectexpect基础在使⽤expect时,基本上都是和以下四个命令打交道:命令作⽤send ⽤于向进程发送字符串expect 从进程接收字符串spawn 启动新的进程interact 允许⽤户交互send命令接收⼀个字符串参数,并将该参数发送到进程。

expect命令和send命令相反,expect通常⽤来等待⼀个进程的反馈,我们根据进程的反馈,再发送对应的交互命令。

spawn命令⽤来启动新的进程,spawn后的send和expect命令都是和使⽤spawn打开的进程进⾏交互。

interact命令⽤的其实不是很多,⼀般情况下使⽤spawn、send和expect命令就可以很好的完成我们的任务;但在⼀些特殊场合下还是需要使⽤interact命令的,interact命令主要⽤于退出⾃动化,进⼊⼈⼯交互。

⽐如我们使⽤spawn、send和expect命令完成了ftp登陆主机,执⾏下载⽂件任务,但是我们希望在⽂件下载结束以后,仍然可以停留在ftp命令⾏状态,以便⼿动的执⾏后续命令,此时使⽤interact命令就可以很好的完成这个任务。

linux设备模型_uevent

linux设备模型_uevent

Linux设备模型(3)_Uevent作者:蜗蜗发布于:2014-3-10 20:391. Uevent的功能Uevent是Kobject的一部分,用于在Kobject状态发生改变时,例如增加、移除等,通知用户空间程序。

用户空间程序收到这样的事件后,会做相应的处理。

该机制通常是用来支持热拔插设备的,例如U盘插入后,USB 相关的驱动软件会动态创建用于表示该U盘的device结构(相应的也包括其中的kobject),并告知用户空间程序,为该U盘动态的创建/dev/目录下的设备节点,更进一步,可以通知其它的应用程序,将该U盘设备mount到系统中,从而动态的支持该设备。

2. Uevent在kernel中的位置下面图片描述了Uevent模块在内核中的位置:由此可知,Uevent的机制是比较简单的,设备模型中任何设备有事件需要上报时,会触发Uevent提供的接口。

Uevent模块准备好上报事件的格式后,可以通过两个途径把事件上报到用户空间:一种是通过kmod模块,直接调用用户空间的可执行文件;另一种是通过netlink通信机制,将事件从内核空间传递给用户空间。

注1:有关kmod和netlink,会在其它文章中描述,因此本文就不再详细说明了。

3. Uevent的内部逻辑解析3.1 Source Code位置Uevent的代码比较简单,主要涉及kobject.h和kobject_uevent.c两个文件,如下:include/linux/kobject.hlib/kobject_uevent.c3.2 数据结构描述kobject.h定义了uevent相关的常量和数据结构,如下:kobject_action 1: /* include/linux/kobject.h, line 50 */2: enum kobject_action {3: KOBJ_ADD,4: KOBJ_REMOVE,5: KOBJ_CHANGE,6: KOBJ_MOVE,7: KOBJ_ONLINE,8: KOBJ_OFFLINE,9: KOBJ_MAX10: };kobject_action定义了event的类型,包括:ADD/REMOVE,Kobject(或上层数据结构)的添加/移除事件。

Linux设备模型 热插拔、mdev 与 firmware

Linux设备模型 热插拔、mdev 与 firmware

Linux设备驱动程序学习(15)-Linux设备模型(热插拔、mdev 与firmware)热插拔有2 个不同角度来看待热插拔:从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。

从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和mdev)的交互。

当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。

现在的计算机系统,要求Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。

这就对设备驱动作者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。

热插拔工具当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在/proc/sys/kernel/hotplug文件里查找处理设备连接的用户空间程序。

这个用户空间程序主要有hotplug:这个程序是一个典型的bash 脚本,只传递执行权给一系列位于/etc/hot-plug.d/ 目录树的程序。

hotplug 脚本搜索所有的有 .hotplug 后缀的可能对这个事件进行处理的程序并调用它们, 并传递给它们许多不同的已经被内核设置的环境变量。

(基本已被淘汰,具体内容请参阅《LDD3》)udev :用于linux2.6.13或更高版本的内核上,为用户空间提供使用固定设备名的动态/dev目录的解决方案。

它通过在sysfs 的/class/ 和/block/ 目录树中查找一个称为dev 的文件,以确定所创建的设备节点文件的主次设备号。

所以要使用udev,驱动必须为设备在sysfs中创建类接口及其dev属性文件,方法和sculld模块中创建dev属性相同。

udev的资料网上十分丰富,我就不在这废话了,给出以下链接有兴趣的自己研究:mdev:一个简化版的udev,是busybox所带的程序,十分适合嵌入式系统。

因为hotplug现在也在被慢慢地淘汰,udev不再依赖hotplug了,所以这里不再介绍;udev较mdev复杂,不太适合嵌入式使用。

底层节点uevent机制

底层节点uevent机制

底层节点uevent机制
底层节点uevent机制是指在Linux系统下,底层节点对于设备的事件通知机制。

底层节点是指设备文件系统中的最底层节点,也就是设备文件的具体实现部分,而uevent则是指用户空间与内核空间之间的事件通知机制。

在Linux系统中,底层节点uevent机制主要用于设备的热插拔、设备状态变化以及驱动程序的加载卸载等操作。

当一个设备被插入或者拔出时,底层节点会向内核发送一个uevent事件,内核会通过uevent机制将这个事件通知到用户空间,用户空间可以根据这个事件来进行相应的操作。

底层节点uevent机制的实现依赖于sysfs文件系统,每个设备在sysfs中都有一个对应的目录,该目录下包含了该设备的属性信息和uevent文件。

当设备发生变化时,底层节点会在uevent文件中写入相应的事件信息,内核会通过sysfs文件系统将这个事件通知到用户空间。

总的来说,底层节点uevent机制是Linux系统下设备管理的重要机制之一,它可以实现设备的热插拔和状态变化的实时通知,为系统的设备管理提供了强大的支持。

- 1 -。

Linux设备模型 热插拔mdev 与 firmware

Linux设备模型 热插拔mdev 与 firmware

Linux设备模型热插拔、mdev 与 firmwareLinux设备驱动程序学习(15)-Linux设备模型(热插拔、mdev 与 firmware)热插拔有 2 个不同角度来看待热插拔:从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。

从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和 mdev)的交互。

当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。

现在的计算机系统,要求 Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。

这就对设备驱动作者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。

热插拔工具当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在/proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序。

这个用户空间程序主要有hotplug:这个程序是一个典型的 bash 脚本,只传递执行权给一系列位于 /etc/hot-plug.d/ 目录树的程序。

hotplug 脚本搜索所有的有 .hotplug 后缀的可能对这个事件进行处理的程序并调用它们, 并传递给它们许多不同的已经被内核设置的环境变量。

(基本已被淘汰,具体内容请参阅《LDD3》)udev :用于linux2.6.13或更高版本的内核上,为用户空间提供使用固定设备名的动态/dev目录的解决方案。

它通过在 sysfs 的 /class/ 和/block/ 目录树中查找一个称为 dev 的文件,以确定所创建的设备节点文件的主次设备号。

所以要使用udev,驱动必须为设备在sysfs中创建类接口及其dev属性文件,方法和sculld模块中创建dev属性相同。

udev的资料网上十分丰富,我就不在这废话了,给出以下链接有兴趣的自己研究:《UDEV Primer》(英文),地址:/decibelshelp/LinuxHelp_UDEVPrimer.html 《udev规则编写》(luofuchong翻译),地址:/luofuchong/archive/2021/12/18/37831.html 《什么是udev》地址:/steganography/archive/2021/04/10/657620.aspx《udev-FAQ 中文翻译》地址:/3225765.html 《udev轻松上路》地址:/user1/3313/archives/2021/1635169.shtml 《Udev (简体中文)》地址:/index.php/Udev_(????????-???) Udev官方主页:/pub/linux/utils/kernel/hotplug/udev.html 下载地址:/pub/linux/utils/kernel/hotplug/ 在《LFS》中也有介绍udev的使用,很值得参考!下载地址:/lfs/downloads/stable/mdev:一个简化版的udev,是busybox所带的程序,十分适合嵌入式系统。

电源管理方式的变更,driver.pm.suspend

电源管理方式的变更,driver.pm.suspend

电源管理⽅式的变更,driver.pm.suspend 与 i2c_driver.suspend 新版linux系统设备架构中关于电源管理⽅式的变更based on linux-2.6.32⼀、设备模型各数据结构中电源管理的部分linux的设备模型通过诸多结构体来联合描述,如struct device,struct device_type,struct class,struct device_driver,struct bus_type等。

@kernel/include/linux/devices.h中有这⼏中结构体的定义,这⾥只列出和PM有关的项,其余查看源码:struct device{...struct dev_pm_info power;...}struct device_type {...int (*uevent)(struct device *dev, struct kobj_uevent_env *env);char *(*devnode)(struct device *dev, mode_t *mode);void (*release)(struct device *dev);const struct dev_pm_ops *pm;};struct class {...void (*class_release)(struct class *class);void (*dev_release)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);const struct dev_pm_ops *pm;...};struct device_driver {...int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (*shutdown) (struct device *dev);int (*suspend) (struct device *dev, pm_message_t state);int (*resume) (struct device *dev);const struct dev_pm_ops *pm;...};struct bus_type {...int (*match)(struct device *dev, struct device_driver *drv);int (*uevent)(struct device *dev, struct kobj_uevent_env *env);int (*probe)(struct device *dev);int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);const struct dev_pm_ops *pm;...};以上可以看出和电源管理相关的两个结构体是struct dev_pm_info和struct dev_pm_ops,他们定义于⽂件@kernel/include/linux/pm.hstruct dev_pm_info {pm_message_t power_state;unsigned int can_wakeup:1;unsigned int should_wakeup:1;enum dpm_state status;#ifdef CONFIG_PM_SLEEPstruct list_head entry;#endif#ifdef CONFIG_PM_RUNTIME // undefstruct timer_list suspend_timer;unsigned long timer_expires;struct work_struct work;wait_queue_head_t wait_queue;spinlock_t lock;atomic_t usage_count;atomic_t child_count;unsigned int disable_depth:3;unsigned int ignore_children:1;unsigned int idle_notification:1;unsigned int request_pending:1;unsigned int deferred_resume:1;enum rpm_request request;enum rpm_status runtime_status;int runtime_error;#endif};struct dev_pm_ops {int (*prepare)(struct device *dev);void (*complete)(struct device *dev);int (*suspend)(struct device *dev);int (*resume)(struct device *dev);int (*freeze)(struct device *dev);int (*thaw)(struct device *dev);int (*poweroff)(struct device *dev);int (*restore)(struct device *dev);int (*suspend_noirq)(struct device *dev);int (*resume_noirq)(struct device *dev);int (*freeze_noirq)(struct device *dev);int (*thaw_noirq)(struct device *dev);int (*poweroff_noirq)(struct device *dev);int (*restore_noirq)(struct device *dev);int (*runtime_suspend)(struct device *dev);int (*runtime_resume)(struct device *dev);int (*runtime_idle)(struct device *dev);};⼆、device中的dev_pm_info结构体device结构体中的power项⽤来将该设备纳⼊电源管理的范围,记录电源管理的⼀些信息。

SELinux概述

SELinux使用了分级的强制访问控制,是Linux核的重要安全措施。

SELinux的安全策略工具可从oss.tresys./projects下载。

本章分析了SELinux的安全机制,介绍了安全策略配置语言、核策略库的结构,简述了SELinux核模块的实现,还分析了用户空间的客体管理器。

3.1 SELinux概述SELinux是安全增强了的Linux,是Security-enhanced Linux的简写,SELinux改进了对核对象和服务的访问控制,改进了对进程初始化、继承和程序执行的访问控制,改进了对文件系统、目录、文件和打开文件描述的访问控制,还改进了对端口、信息和网络接口的访问控制。

早期的Linux核只提供了经典的UNIX自主访问控制(root用户,用户ID,模式位安全机制),以及部分地支持了POSIX.1e标准草案中的capabilities安全机制,这对于Linux系统的安全性是不够的,NSA(the National Security Agency)和SCC(Secure Computing Corporation)共同开发了强大的基于类型加强(Type Enforcement)的强制访问控制(mandatory access control,简称MAC)机制,提供了动态的安全策略机制。

Linux核增加了一个通用的安全访问控制框架,它通过hook函数来控制程序的执行,这个框架就是Linux安全模块(LSM),在LSM上可使用各种安全控制机制(如:Flask机制)来实现对程序的控制。

SELinux应用了类型加强(Type Enforcement,TE)和基于角色访问控制(role-based access control,RBAC)技术。

TE给每个主体(进程)和系统中的客体定义了一个类型,这些类型定义在SELinux的安全策略文件中,以安全标签形式存放在文件本身的扩展属性(extended attributes,简称xattrs)里。

Linux设备模型浅析之设备篇

Linux设备模型浅析之设备篇本文属本人原创,欢转载,转载请注明出处。

由于个人的见识和能力有限,不可能面面俱到,也可能存在谬误,敬请网友指出,本人的邮箱是yzq.seen@,博客是。

Linux设备模型,仅仅看理论介绍,比如LDD3的第十四章,会感觉太抽象不易理解,而通过阅读内核代码就更具体更易理解,所以结合理论介绍和内核代码阅读能够更快速的理解掌握linux设备模型。

这一序列的文章的目的就是在于此,看这些文章之前最好能够仔细阅读LDD3的第十四章。

大部分device和driver都被包含在一个特定bus中,platform_device和platform_driver就是如此,包含在platform_bus_type中。

这里就以对platform_bus_type的调用为主线,浅析platform_device的注册过程,从而理解linux设备模型。

platform_bus_type用于关联SOC的platform device和platform driver,比如在内核linux-2.6.29中所有S3C2410中的platform device都保存在devs.c中。

这里就以S3C2410 RTC为例。

在文章的最后贴有一张针对本例的device model图片,可在阅读本文章的时候作为参照。

一、S3C2410 RTC的platform device定义在arch/arm/plat-s3c24xx/devs.c中,如下:static struct resource s3c_rtc_resource[] = {[0] = {.start = S3C24XX_PA_RTC,.end = S3C24XX_PA_RTC + 0xff,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_RTC,.end = IRQ_RTC,.flags = IORESOURCE_IRQ,},[2] = {.start = IRQ_TICK,.end = IRQ_TICK,.flags = IORESOURCE_IRQ}};struct platform_device s3c_device_rtc = {.name = "s3c2410-rtc",.id = -1,.num_resources = ARRAY_SIZE(s3c_rtc_resource),.resource = s3c_rtc_resource,};把它们添加在arch/arm/mach-s3c2440/ mach- smdk2440.c中,如下:static struct platform_device *smdk2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_iis,& s3c_device_rtc};系统初始化的时候会调用drivers/base/platform.c里的platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices))将其注册到platform_bus_type,最终被添加到device hierarchy 。

input(evdev)

Linux输入子系统框架2012-10-13 17:58:13Linux输入子系统包括三个层次:事件处理层(Event Handler)、核心层(Input Core)和驱动层(Input Driver)。

1.事件层负责与用户程序打交道,将核心层传来的事件报告给用户程序。

2.核心层是链接其他两个层之间的纽带与桥梁,向下提供驱动层的接口,向上提供事件处理层的接口。

3.驱动层负责操作具体的硬件设备,这层的代码是针对具体的驱动程序的,键盘、鼠标、触摸屏等字符设备驱动功能的实现工作主要在这层。

在Linux输入子系统中,有几个重要的结构体,掌握这些结构体对理解整个输入子系统有很大的帮助:input_dev结构体用来描述一个input设备,位于设备驱动层,一个设备能产生哪类以及该类事件中的哪些事件都是在该结构体中声明的。

struct input_dev{const char *name;struct input_id id;unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; // 表示能产生哪类事件unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; // 表示能产生哪些按键unsigned long relbit[BITS_TO_LONGS(REL_CNT)];unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];unsigned long key[BITS_TO_LONGS(KEY_CNT)];int (*open)(struct input_dev *dev);void (*close)(struct input_dev *dev);struct input_handle *grab;struct device dev;struct list_head h_list;struct list_head node;......};input_handler结构体用来描述一个事件处理器,结构体中的input_device_id*id_table;成员用来和input_dev设备匹配,看是否支持该输入设备。

linux vtune 用法

linux vtune 用法VTune是Intel提供的一款性能分析工具,可以用于对Linux系统的应用程序进行性能分析和优化。

使用VTune进行Linux性能分析的一般步骤如下:1.安装VTune:首先需要从Intel官网下载并安装VTune软件包。

2.收集性能数据:使用VTune运行目标程序,并根据需求配置所需的分析类型、采样频率和持续时间等参数。

VTune可以对CPU利用率、内存访问、I/O操作等进行分析。

收集的性能数据可以保存到一个文件中。

3.分析性能数据:通过命令行界面或者图形界面打开VTune的分析器,然后将收集到的性能数据加载到分析器中。

VTune会根据加载的性能数据生成相应的分析报告,包括热点函数、线程活动、内存分配等多个方面的信息。

4.优化性能:根据分析报告中的信息,定位性能瓶颈,并提出相应的优化建议。

可以通过调整代码、算法、并行化结构等方式来改进程序的性能。

此外,VTune还提供了许多功能和选项,可以帮助用户更深入地分析和优化程序,例如:-支持多种分析器和事件:VTune提供了多个分析器,可以针对不同的性能指标进行分析,例如CPU利用率、内存带宽、磁盘I/O等。

用户可以选择适合自己需求的分析器,并指定需要监视的性能指标。

-支持命令行和图形界面:VTune可以通过命令行界面或者图形界面来操作,用户可以根据自己的习惯选择使用方式。

-支持远程分析:VTune还支持通过网络对远程Linux系统进行性能分析,用户可以在本地机器上运行VTune并分析远程系统的性能。

-支持多种编程语言和平台:VTune可以用于分析多种编程语言和平台的程序,包括C、C++、Fortran等,并支持Intel和非Intel的处理器架构。

总结而言,VTune是一款强大的Linux性能分析工具,通过收集、分析和优化性能数据,可以帮助开发人员提高程序的性能和效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
/* 在本例中是 devices_kset 容器,详细介绍可参照《Linux 设备模型浅析之设备篇》,后 面将列出 devices_kset 的定义 */ kset = top_kobj->kset; uevent_ops = kset->uevent_ops; // 本例中 uevent_ops = &device_uevent_ops
struct sk_buff *skb; size_t len;
/* allocate message with the maximum possible size */ len = strlen(action_string) + strlen(devpath) + 2; skb = alloc_skb(len + env->buflen, GFP_KERNEL); if (skb) {
return 0; }
// 获得用于存放环境变量的 buffer /* environment buffer */ env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); if (!env)
return -ENOMEM;
/* 获取该 kobj 在 sysfs 的路径,通过遍历其父 kobj 来获得,本例是/sys/devices/platform/ s3c2410-rtc/rtc/rtc0 */ /* complete object path */
goto exit;
/* 如果配置了网络,那么就会通过 netlink socket 向用户空间发送环境标量,而用户空间 则通过 netlink socket 接收,然后采取一些列的动作。这种机制目前用在 udev 中,也就是 pc 机系统中,后面会分析*/ #if defined(CONFIG_NET) /* send netlink message */ /* 如果配置了 net,则会在 kobject_uevent_init()例程中将全局比昂俩 uevent_sock 初试化 为 NETLINK_KOBJECT_UEVENT 类型的 socket。*/ if (uevent_sock) {
一、在《Linux 设备模型浅析之设备篇》中介绍过 device_add()例程,其用于将一个 device 注册到 device model,其中调用了 kobject_uevent(&dev->kobj, KOBJ_ADD)例程向用户空间发出 KOBJ_ADD 事件并输出环境变量,以表明一个 device 被添加了。在《Linux 设备模型浅析之设 备篇》中介绍过 rtc_device_register()例程 ,其最终调用 device_add()例程添加了一个 rtc0 的 device,我们就以它为例子来完成 uevent 的分析。让我们看看 kobject_uevent()这个例程的代 码,如下: int kobject_uevent(struct kobject *kobj, enum kobject_action action) {
retval = uevent_ops->uevent(kset, kobj, env); if (retval) {
pr_debug("kobject: '%s' (%p): %s: uevent() returned " "%d\n", kobject_name(kobj), kobj, __func__, retval);
pr_debug("kobject: '%s' (%p): %s\n", kobject_name(kobj), kobj, __func__);
/* search the kset we belong to */ top_kobj = kobj; /* 找到其所属的 kset 容器,如果没找到就从其父 kobj 找,一直持续下去,直到父 kobj 不 存在 */ while (!top_kobj->kset && top_kobj->parent)
Linux 设备模型浅析之 uevent 篇
本文属本人原创,欢迎转载,转载请注明出处。由于个人的见识和能力有限,不可能面 面俱到,也可能存在谬误,敬请网友指出,本人的邮箱是 yzq.seen@,博客是 。
Linux 设备模型,仅仅看理论介绍,比如 LDD3 的第十四章,会感觉太抽象不易理解,而 通过阅读内核代码就更具体更易理解,所以结合理论介绍和内核代码阅读能够更快速的理解掌 握 linux 设备模型。这一序列的文章的目的就是在于此,看这些文章之前最好能够仔细阅读 LDD3 的第十四章。uevent,即 user space event,就是内核向用户空间发出的一个事件通知,使 得应用程序能有机会对该 event 作出反应,udev 及 mdev(busybox)就是这种应用程序。阅读这篇 文章之前,最好先阅读文章《Linux 设备模型浅析之设备篇》和《Linux 设备模型浅析之驱动 篇》。
goto exit;
/* keys passed in from the caller */
if (envp_ext) {
// 为 NULL,不执行
for (i = 0; envp_ext[i]; i++) {
retval = add_uevent_var(env, "%s", envp_ext[i]);
}
/* 回调 uevent_ops-> name (),本例中是 dev_uevent_name()例程,获取 bus 或 class 的名 字,本例中 rtc0 不存在 bus,所以是 class 的名字“rtc”,后面分析 */ /* originating subsystem */ if (uevent_ops && uevent_ops->name)
char *envp_ext[]) {
struct kobj_uevent_env *env; const char *action_string = kobject_actions[action]; // 本例是“add”命令 const char *devpath = NULL; const char *subsystem; struct kobject *top_kobj; struct kset *kset; struct kset_uevent_ops *uevent_ops; u64 seq; int i = 0; int retval = 0;
kobj->state_add_uevent_sent = 1; else if (action == KOBJ_REMOVE)
kobj->state_remove_uevent_sent = 1;
/* 增加 event 序列号的值,并输出到环境变量的 buffer。该系列号可以从/sys/kernel/ uevent_seqnum 属性文件读取,至于 ue录是怎样产 生的,后面会分析 */ /* we will send an event, so request a new sequence number */ spin_lock(&sequence_lock); seq = ++uevent_seqnum; spin_unlock(&sequence_lock); retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); if (retval)
if (retval)
goto exit;
}
}
// 回调 uevent_ops->uevent(),本例中是 dev_uevent()例程,输出一些环境变量,后面分析
/* let the kset specific function add its stuff */ if (uevent_ops && uevent_ops->uevent) {
subsystem = uevent_ops->name(kset, kobj); else
subsystem = kobject_name(&kset->kobj); if (!subsystem) {
pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the " "event to drop!\n", kobject_name(kobj), kobj, __func__);
if (!uevent_ops->filter(kset, kobj)) { // 如果不成功,即 uevent suppress,则直接返回 pr_debug("kobject: '%s' (%p): %s: filter function " "caused the event to drop!\n", kobject_name(kobj), kobj, __func__); return 0;
top_kobj = top_kobj->parent;
if (!top_kobj->kset) { pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " "without kset!\n", kobject_name(kobj), kobj, __func__); return -EINVAL;
/* 回调 uevent_ops->filter ()例程,本例中是 dev_uevent_filter()例程,主要是检查是否 uevent suppress,后面分析 */ /* skip the event, if the filter returns zero. */ if (uevent_ops && uevent_ops->filter)
相关文档
最新文档