#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");
阅读(685) | 评论(0) | 转发(0) |