#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef unsigned char ui_08;
typedef unsigned short ui_16;
typedef unsigned int ui_32;
typedef char si_08;
typedef short si_16;
typedef int si_32;
static unsigned long flag=1;
static struct mutex uevent_sock_mutex;
static ssize_t att_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
size_t count=0;
count =sprintf(&buf[count],"%lu\n",flag);
return count;
}
static ssize_t att_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
{
int retval=-1;
struct kobj_uevent_env *env;
char *devpath;
char *action_string="test_action";
flag=buf[0]-'0';
//通过kobject_uevent来将内核对象kobj的状态变化通知用户程序
switch(flag)
{
case 0:
kobject_uevent(kobj,kobj_add);
break;
case 1:
kobject_uevent(kobj,kobj_remove);
break;
case 2:
kobject_uevent(kobj,kobj_change);
break;
case 3:
kobject_uevent(kobj,kobj_move);
break;
case 4:
kobject_uevent(kobj,kobj_online);
break;
case 5:
kobject_uevent(kobj,kobj_offline);
env = kzalloc(sizeof(struct kobj_uevent_env), gfp_kernel);
if (!env)
return -enomem;
/* complete object path */
devpath = kobject_get_path(kobj, gfp_kernel);
if (!devpath) {
retval = -enoent;
}
/* default keys */
retval = add_uevent_var(env, "action=%s", action_string);
retval = add_uevent_var(env, "devpath=%s", devpath);
//根据形参和获取的subsystem和devpath的值设置默认的环境变量 -
mutex_lock(&uevent_sock_mutex);
mutex_unlock(&uevent_sock_mutex);
kfree(env);
break;
}
return count;
}
static struct attribute cld_att={
.name="cldatt",
.mode=s_irugo|s_iwusr,
};
static const struct sysfs_ops att_ops={
.show=att_show,
.store=att_store,
};
static struct kobj_type cld_ktype={
.sysfs_ops=&att_ops,
};
static struct kobject *parent;
static struct kobject *child;
static struct kset *c_kset;
static int kobj_demo_init(void)
{
int err;
parent=kobject_create_and_add("pa_obj",null);
child=kzalloc(sizeof(*child),gfp_kernel);
if(!child)
return ptr_err(child);
//一个能够通知用户空间状态变化的kobject必须隶属于某一个kset,也就是
//所谓的subsystem,所以此处给内核对象child创建一个kset对象c_kset
c_kset=kset_create_and_add("c_kset",null,parent);
if(!c_kset)
return -1;
child->kset=c_kset;
err=kobject_init_and_add(child,&cld_ktype,parent,"cld_obj");
if(err)
return err;
//为内核对象child创建一个属性文件
err=sysfs_create_file(child,&cld_att);
mutex_init(&uevent_sock_mutex);
return err;
}
static void kobj_demo_exit(void)
{
sysfs_remove_file(child,&cld_att);
kset_unregister(c_kset);
kobject_del(child);
kobject_del(parent);
}
module_init(kobj_demo_init);
module_exit(kobj_demo_exit);
module_license("gpl");
阅读(607) | 评论(0) | 转发(0) |