kobject对象可以通过uevent机制往用户空间发送信息
kobject_uevent:内核消息发送接口
NETLINK:特殊的网络通信,本地主机使用
udev/mdev:用户空间守护进程,监听广播信息
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOVE,
KOBJ_ONLINE,
KOBJ_OFFLINE,
KOBJ_BIND,
KOBJ_UNBIND,
KOBJ_MAX
};
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[])
{
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);
...
}
include/linux/device.h
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key);\
})
struct class *__class_create(struct module *owner, const char *name,
struct lock_class_key *key)
include/linux/device.h
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对象的名字