Linux下的uevent

article/2025/9/7 11:48:03

查找linux的uevent节点(find /sys -name uevent),大概有1000多个,那这些节点是怎么实现的呢。

 

 drivers/base/core.c

有如下代码,每创建一个device,都会创建一个event节点

static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,char *buf)
{...retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);...	
}static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
{}
static DEVICE_ATTR_RW(uevent);int device_add(struct device *dev)
{...device_create_file(dev, &dev_attr_uevent);...
}

来个demo看下

#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>static struct class *demo_class;
static struct cdev demo_cdev;
dev_t demo_number = 0;
int demo_open (struct inode *inode, struct file *filp)
{return 0;
}static  struct file_operations demo_nod_fops =
{.owner = THIS_MODULE,.open  = demo_open,
};int demo_uevent(struct device *dev, struct kobj_uevent_env *env)
{int ret = 0;char *p="aaa";char *q="bbb";ret = add_uevent_var(env, "demo_NAME=%s",p);ret = add_uevent_var(env, "demo_NAME=%s",q);return ret;
}static int __init example_init(void)
{int ret;demo_number=MKDEV(0,0);ret=alloc_chrdev_region(&demo_number,0,1,"6");if(ret<0){printk("alloc chardev region err\n");return ret;}cdev_init(&demo_cdev,&demo_nod_fops);demo_cdev.owner=THIS_MODULE;ret=cdev_add(&demo_cdev,demo_number,1);if(ret<0){printk("add demo cdev err!\n");return ret;}demo_class=class_create(THIS_MODULE,"demo");if(IS_ERR(demo_class)){printk("create demo class err!\n");return -1;}device_create(demo_class,NULL,demo_number,NULL,"66"); demo_class->dev_uevent = demo_uevent;return 0;
}static void __exit example_exit(void)
{cdev_del(&demo_cdev);device_destroy(demo_class,demo_number);unregister_chrdev_region(demo_number, 1);class_destroy(demo_class);
}module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");

 在代码中,还会看到通过uevent给上层发信息,如

电量变化,插拔充电器

static void power_supply_changed_work(struct work_struct *work)
{
...
kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE);
...
}int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{return kobject_uevent_env(kobj, action, NULL);
}int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
{
...
#if defined(CONFIG_NET)/* send netlink message */list_for_each_entry(ue_sk, &uevent_sock_list, list) {struct sock *uevent_sock = ue_sk->sk;struct sk_buff *skb;size_t len;if (!netlink_has_listeners(uevent_sock, 1))continue;/* allocate message with the maximum possible size */len = strlen(action_string) + strlen(devpath) + 2;skb = alloc_skb(len + env->buflen, GFP_KERNEL);if (skb) {char *scratch;/* add header */scratch = skb_put(skb, len);sprintf(scratch, "%s@%s", action_string, devpath);/* copy keys to our continuous event payload buffer */for (i = 0; i < env->envp_idx; i++) {len = strlen(env->envp[i]) + 1;scratch = skb_put(skb, len);strcpy(scratch, env->envp[i]);}NETLINK_CB(skb).dst_group = 1;retval = netlink_broadcast_filtered(uevent_sock, skb,0, 1, GFP_KERNEL,kobj_bcast_filter,kobj);/* ENOBUFS should be handled in userspace */if (retval == -ENOBUFS || retval == -ESRCH)retval = 0;} elseretval = -ENOMEM;}
#endif
...
}

来个demo看下

/** Sample kset and ktype implementation** Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>* Copyright (C) 2007 Novell Inc.** Released under the GPL version 2 only.**/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>/** This module shows how to create a kset in sysfs called* /sys/kernel/kset-example* Then tree kobjects are created and assigned to this kset, "foo", "baz",* and "bar".  In those kobjects, attributes of the same name are also* created and if an integer is written to these files, it can be later* read out of it.*//** This is our "object" that we will create a few of and register them with* sysfs.*/
struct foo_obj {struct kobject kobj;int bar;int baz;
};
#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)/* a custom attribute that works just for a struct foo_obj. */
struct foo_attribute {struct attribute attr;ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
};
#define to_foo_attr(x) container_of(x, struct foo_attribute, attr)/** The default show function that must be passed to sysfs.  This will be* called by sysfs for whenever a show function is called by the user on a* sysfs file associated with the kobjects we have registered.  We need to* transpose back from a "default" kobject to our custom struct foo_obj and* then call the show function for that specific object.*/
static ssize_t attr_show(struct kobject *kobj,struct attribute *attr,char *buf)
{struct foo_attribute *attribute;struct foo_obj *foo;attribute = to_foo_attr(attr);foo = to_foo_obj(kobj);if (!attribute->show)return -EIO;return attribute->show(foo, attribute, buf);
}/** Just like the default show function above, but this one is for when the* sysfs "store" is requested (when a value is written to a file.)*/
static ssize_t attr_store(struct kobject *kobj,struct attribute *attr,const char *buf, size_t len)
{struct foo_attribute *attribute;struct foo_obj *foo;attribute = to_foo_attr(attr);foo = to_foo_obj(kobj);if (!attribute->store)return -EIO;return attribute->store(foo, attribute, buf, len);
}/* Our custom sysfs_ops that we will associate with our ktype later on */
static const struct sysfs_ops sysfs_ops = {.show = attr_show,.store = attr_store,
};/** The release function for our object.  This is REQUIRED by the kernel to* have.  We free the memory held in our object here.** NEVER try to get away with just a "blank" release function to try to be* smarter than the kernel.  Turns out, no one ever is...*/
static void release(struct kobject *kobj)
{struct foo_obj *foo;foo = to_foo_obj(kobj);kfree(foo);
}static ssize_t bar_show(struct foo_obj *foo_obj, struct foo_attribute *attr, char *buf)
{return sprintf(buf, "%d\n", foo_obj->bar);
}static ssize_t bar_store(struct foo_obj *foo_obj, struct foo_attribute *attr, const char *buf, size_t count)
{int ret;ret = kstrtoint(buf, 10, &foo_obj->bar);if (ret < 0)return ret;return count;	
}static ssize_t baz_show(struct foo_obj *foo_obj, struct foo_attribute *attr,char *buf)
{return sprintf(buf, "%d\n", foo_obj->baz);
}static ssize_t baz_store(struct foo_obj *foo_obj, struct foo_attribute *attr,const char *buf, size_t count)
{int ret;ret = kstrtoint(buf, 10, &foo_obj->baz);if (ret < 0)return ret;return count;
}static struct foo_attribute bar_attribute =__ATTR(bar, 0664, bar_show, bar_store);
static struct foo_attribute baz_attribute =__ATTR(baz, 0664, baz_show, baz_store);/** Create a group of attributes so that we can create and destroy them all* at once.*/
static struct attribute *default_attrs[] = {&bar_attribute.attr,&baz_attribute.attr,NULL,	/* need to NULL terminate the list of attributes */
};/** Our own ktype for our kobjects.  Here we specify our sysfs ops, the* release function, and the set of default attributes we want created* whenever a kobject of this type is registered with the kernel.*/
static struct kobj_type ktype = {.sysfs_ops = &sysfs_ops,.release = release,.default_attrs = default_attrs,
};static struct kset *example_kset;
static struct foo_obj *bar_obj;
static struct foo_obj *baz_obj;static struct foo_obj *create_foo_obj(const char *name)
{struct foo_obj *foo;int retval;/* allocate the memory for the whole object */foo = kzalloc(sizeof(*foo), GFP_KERNEL);if (!foo)return NULL;/** As we have a kset for this kobject, we need to set it before calling* the kobject core.*/foo->kobj.kset = example_kset;/** Initialize and add the kobject to the kernel.  All the default files* will be created here.  As we have already specified a kset for this* kobject, we don't have to set a parent for the kobject, the kobject* will be placed beneath that kset automatically.*/retval = kobject_init_and_add(&foo->kobj, &ktype, NULL, "%s", name);if (retval) {kobject_put(&foo->kobj);return NULL;}/** We are always responsible for sending the uevent that the kobject* was added to the system.*/kobject_uevent(&foo->kobj, KOBJ_ADD);return foo;
}static void destroy_foo_obj(struct foo_obj *foo)
{kobject_put(&foo->kobj);
}static int __init example_init(void)
{/** Create a kset with the name of "kset_example",* located under /sys/kernel/*/example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);if (!example_kset)return -ENOMEM;bar_obj = create_foo_obj("bar");if (!bar_obj)goto bar_error;baz_obj = create_foo_obj("baz");if (!baz_obj)goto baz_error;return 0;baz_error:destroy_foo_obj(bar_obj);
bar_error:kset_unregister(example_kset);return -EINVAL;
}static void __exit example_exit(void)
{destroy_foo_obj(baz_obj);destroy_foo_obj(bar_obj);kset_unregister(example_kset);
}module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");

应用层监听

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>void MonitorNetlinkUevent()
{int sockfd;struct sockaddr_nl sa;int len;char buf[4096];struct iovec iov;struct msghdr msg;int i;memset(&sa, 0, sizeof(sa));sa.nl_family = AF_NETLINK;sa.nl_groups = NETLINK_KOBJECT_UEVENT;sa.nl_pid = 0;		//getpid(); both is okmemset(&msg, 0, sizeof(msg));iov.iov_base = (void *)buf;iov.iov_len = sizeof(buf);msg.msg_name = (void *)&sa;msg.msg_namelen = sizeof(sa);msg.msg_iov = &iov;msg.msg_iovlen = 1;sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);if (sockfd == -1)printf("socket creating failed:%s\n", strerror(errno));if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1)printf("bind error:%s\n", strerror(errno));len = recvmsg(sockfd, &msg, 0);if (len < 0)printf("receive error\n");else if (len < 32 || len > sizeof(buf))printf("invalid message");for (i = 0; i < len; i++)if (*(buf + i) == '\0')buf[i] = '\n';printf("received %d bytes\n%s\n", len, buf);close(sockfd);
}int main(int argc, char **argv)
{printf("***********************start***********************\n");MonitorNetlinkUevent();printf("***********************ends************************\n");return 0;
}

运行结果

 


http://chatgpt.dhexx.cn/article/iWAW9CIq.shtml

相关文章

Android UEvent事件分析

1.背景概述 众所周知,在安卓系统中有状态栏,在插入外设的时候,会在顶部状态栏显示小图标。 比如,camera设备,耳机设备,U盘,以及电池等等。这些都需要在状态栏动态显示。 从上面这张图片可以看出这些设备都有自己的服务一直在跑,并且都是继承了UEventObserver.java这个…

嵌入式Linux——uevent机制:uevent原理分析

简介&#xff1a; 本文主要介绍uevent机制是什么&#xff0c;并通过代码分析使用uevent机制生成设备节点的过程。而本文将分为两部分&#xff0c;第一部分我们介绍一些预备知识和uevent的原理&#xff0c;而第二部分——通过代码介绍使用uevent机制创建设备节点。 Linux内核&am…

uevent机制:uevent原理分析

简介&#xff1a; 本文主要介绍uevent机制是什么&#xff0c;并通过代码分析使用uevent机制生成设备节点的过程。而本文将分为两部分&#xff0c;第一部分我们介绍一些预备知识和uevent的原理&#xff0c;而第二部分——通过代码介绍使用uevent机制创建设备节点。 声明&#…

900 多道 LeetCode 题解,这个 GitHub 项目值得 Star!

公众号关注 “GitHubPorn” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 大家好&#xff0c;我是小 G。 周末风和日丽&#xff0c;适合刷 LeetCode 今天给你们推荐个 GitHub 项目&#xff0c;里面收集了 900 多道 LeetCode 题解&#xff0c;并包含中英文两个版本&…

Leetcode中你的代码执行之后显示超出时间限制

Leetcode中但凡是你的代码执行之后显示超出时间限制 比如&#xff1a; 那么必定是你写的代码不够完善甚至是还存在错误&#xff01;

升职加薪,必不可少!Python刷题打怪,你要的LeetCode答案都在这里了!

对于还不了解LeetCode的同学&#xff0c;那比较厉害了&#xff0c;估计离大厂还有一步距离&#xff01; LeetCode&#xff0c;让程序员进阶的在线平台&#xff0c;找工作备战名企技术面试&#xff01;(文末阅读原文到达学习平台) 本公众号之前陪伴了几期LeetCode的打卡之旅&…

LeetCode 96~100

前言 本文隶属于专栏《LeetCode 刷题汇总》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构请见LeetCode 刷题汇总 正文 幕布 幕布链接 96. 不同的二叉搜索树 题解 官方…

【下载】快速通过Python笔试?学大家一样先把LeetCode答案私藏了

如今学习python的同学越来越多了&#xff0c;也正是同学们秋招时期&#xff0c;去年分享了LeetCode答案后&#xff0c;已经有上百位同学找到小编开始实践这个平台。 LeetCode&#xff0c;让程序员进阶的在线平台&#xff0c;找工作备战名企技术面试&#xff01;(文末阅读原文到…

面试失败总结,这 577 道 LeetCode 题 Java 版答案你值得拥有

去字节、美团、BAT 等大厂面试&#xff0c;刷 LeetCode 上的数据结构算法题是必修课。许多读者说&#xff0c;刷题的时候经常会遇到困难&#xff0c;想要找一本答案题解做参考。 下面分享几个用 Java 语言实现的开源 LeetCode 题解&#xff0c;也要感谢这些优秀的开源作者们&a…

LeetCode答案大全题(java版)

思路&#xff1a;查找时&#xff0c; 建立索引&#xff08;Hash查找&#xff09; 或进行排序&#xff08;二分查找&#xff09;。本题缓存可在找的过程中建立索引&#xff0c;故一个循环可以求出解&#xff08;总是使用未 使用元素查找使用元素&#xff0c;可以保证每一对都被检…

LeetCode数据库题目汇总一(附答案)

1、基础SQL 数据表: dept: deptno(primary key), dname, loc emp: empno(primary key), ename, job, mgr(references emp(empno)), sal, deptno(references dept(deptno)) 1 列出emp表中各部门的部门号,最高工资,最低工资 select max(sal) as 最高工资,min(sal) as 最…

Leetcode各种题型题目+思路+代码(共176道题及答案)

文章目录 第一章&#xff1a;Leetcode 每日很多题 1、Leetcode-1047 删除字符串中的所有相邻重复项 2、剑指 Offer 53 - I. 在排序数组中查找数字 I 3、Leetcode704:二分查找 4、 Leetcode 227&#xff1a;基本计算器II 5、leetcode 224&#xff1a;基本计算器(带括号的计…

Leetcode Top100题目和答案(Java完整版 面试必备)

二刷完剑指Offer后又刷了一遍Leetcode Top 100专栏的题目&#xff0c;听说基本上能涵盖面试的算法题&#xff0c;总体来说收获还是很大的&#xff0c;下面贴出答案&#xff0c;又不懂的可以给我留言&#xff0c;博主会及时解答。 我的github 准备把春招复习的知识都整理到githu…

数据可视化-柱状图-dict结构MACARONS主题

from pyecharts.charts import Bar from pyecharts.faker import Faker from pyecharts.globals import ThemeTypec (Bar({"theme": ThemeType.MACARONS}).add_xaxis(Faker.choose()).add_yaxis("商家A", Faker.values()).add_yaxis("商家B", F…

echarts图表主题--马卡龙macarons--自己配置主题颜色

用过echarts的人都几道&#xff0c;他的官网风格颜色对比强烈&#xff0c;这样儿式的&#xff1a; 大多时候和你的项目风格难免冲突&#xff0c;它有一些风格配置&#xff0c;我觉得马卡龙这个配色就很好&#xff1a; 当然&#xff0c;既然是配置项&#xff0c;肯定不止这一种…

若依vue --雷达图封装使用

大概效果: 如下 1:封装 <template><div :class"className" :style"{ height: height, width: width }" /> </template><script> import echarts from "echarts"; require("echarts/theme/macarons"); // e…

vuejs集成echarts的一些问题

最近在做Beetlex的数据分析平台&#xff0c;在开发这个产品过程中涉及到大量的数据图表展示功能&#xff1b;由于产品前端使用的是vuejs开发&#xff0c;所以在集成echarts或多或少会碰到一些问题&#xff0c;在这里主要讲解一下碰到的问题和解决方法。 在讲解之前先分享一下实…

Echarts主题构建工具的使用

Echarts自带丰富的主题配色&#xff0c;对于有独立的UI设计&#xff0c;主题的应用范围不是很广泛&#xff0c;但是官方的配色还是具有很大的参考价值的。 传送门&#xff1a;https://echarts.apache.org/zh/theme-builder.html 下载或复制以下的主题保存至 *.js 文件&#x…

Echarts-主题切换

从网上搜索了相关的方法&#xff0c;是主题之前的切换&#xff0c;但是用的是下拉框类型的&#xff0c;也可以设置div样式&#xff0c;参考官网那种 设置一个div&#xff0c;通过三个图片的点击效果实现切换主题的功能 我用的jQuery和Echarts是cdn&#xff0c;如果您想引用js文…

vue项目中Echarts图表完整引入、按需加载以及修改主题色

一、完整引入Echarts 下载安装echarts包 npm install echarts -Soryarn add echarts 定义图表显示的容器&#xff0c;并进行渲染 <template><div id"myChart" ref"myChart"></div> </template><style>#myChart {widt…