本文主要是介绍IMX6LL|class:设备的大管家,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
uevent:内核消息的快递包
uevent机制
kobject对象可以通过uevent机制往用户空间发送信息
-
kobject_uevent:内核消息发送接口
- 广播方式发送
-
NETLINK:特殊的网络通信,本地主机使用
- 传统做法是内核执行hotplug程序进行消息通知(效率低、不优雅)
-
udev/mdev:用户空间守护进程,监听广播信息
- 默认开机启动,systemd
- udevadm monitor:打印uevent事件
内核消息发送
消息类型
enum kobject_action {KOBJ_ADD,KOBJ_REMOVE,KOBJ_CHANGE,KOBJ_MOVE,KOBJ_ONLINE,KOBJ_OFFLINE,KOBJ_BIND,KOBJ_UNBIND,KOBJ_MAX
};
kobject_uevent()函数
int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{return kobject_uevent_env(kobj, action, NULL);
}
kobject_uevent_env()函数
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
{struct kobj_uevent_env *env;...top_kobj = kobj;/*while循坏查找kobj所隶属的最顶层kobject或者kset指针不为空的kobj*/while (!top_kobj->kset && top_kobj->parent)top_kobj = top_kobj->parent;/*判断kobj的kset指针是否为空*/if (!top_kobj->kset) {pr_debug("kobject: '%s' (%p): %s: attempted to send uevent ""without kset!\n", kobject_name(kobj), kobj,__func__);return -EINVAL;}/*得到kobj指向的kset对象*/kset = top_kobj->kset;/*获取kset的uevent_ops*/uevent_ops = kset->uevent_ops;/*若kobject->uevent_suppress为1,表示kobj不适用uevent*/if (kobj->uevent_suppress) {pr_debug("kobject: '%s' (%p): %s: uevent_suppress ""caused the event to drop!\n",kobject_name(kobj), kobj, __func__);return 0;}/*过滤event事件*/if (uevent_ops && uevent_ops->filter)if (!uevent_ops->filter(kset, kobj)) {pr_debug("kobject: '%s' (%p): %s: filter function ""caused the event to drop!\n",kobject_name(kobj), kobj, __func__);return 0;}.../* environment buffer */env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);if (!env)return -ENOMEM;/* 获取kobj在sysfs中的路径 */devpath = kobject_get_path(kobj, GFP_KERNEL);if (!devpath) {retval = -ENOENT;goto exit;}/* 消息内容 */retval = add_uevent_var(env, "ACTION=%s", action_string);if (retval)goto exit;retval = add_uevent_var(env, "DEVPATH=%s", devpath);if (retval)goto exit;retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);if (retval)goto exit;...if (uevent_ops && uevent_ops->uevent) {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);goto exit;}}.../*本地socket通信,发送广播信息*/retval = kobject_uevent_net_broadcast(kobj, env, action_string,devpath);...}
class:设备的大管家
- 硬件设备分类管理
- 与udev协作,自动创建设备文件
创建一个class
include/linux/device.h
class_create宏
#define class_create(owner, name) \
({ \static struct lock_class_key __key; \__class_create(owner, name, &__key);\
})
- owner:一般设置为THIS_MODULE
- name:kobject对象的名字
struct class *__class_create(struct module *owner, const char *name,struct lock_class_key *key)
- struct class里面"继承"了kobject对象
在class下添加kobject对象
include/linux/device.h
device_create()函数
struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
-
class:新构建的class
-
parent:新kobject对象的上一层节点,一般为NULL
-
dev_t:属性文件记录该设备号
-
drvdata:私有数据,一般为NULL
-
fmt:变参参数,一般用来设置kobject对象的名字
这篇关于IMX6LL|class:设备的大管家的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!