#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
#include <linux/kobject.h>
MODULE_AUTHOR("STONE");
MODULE_LICENSE("GPL");
struct kset *kset_p;
struct kset kset_c;
struct kobject kobj;
char attrstr[256];
//kobject
struct attribute attr_str = {
.name = "attr_str",
.mode = S_IRWXU,
};
struct attribute attr_name = {
.name = "attr_name",
.mode = S_IRUSR,
};
static struct attribute *def_attrs[] = {
&attr_str,
&attr_name,
NULL,
};
void obj_test_release(struct kobject *kobject)
{
printk("[call obj_test_release]\n");
}
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr, char* buf)
{
if( !strcmp(attr->name, "attr_str") )
sprintf(buf, "1: %s\n", attrstr);
else
sprintf(buf, "2: %s\n", attr->name);
return strlen(buf);
}
ssize_t kobj_test_store(struct kobject *kobject, struct attribute *attr, const char* buf, size_t count)
{
if( !strcmp(attr->name, "attr_str") )
sprintf(attrstr, "%s", buf);
return count;
}
struct sysfs_ops obj_test_sysops =
{
.show = kobj_test_show,
.store = kobj_test_store,
};
struct kobj_type ktype =
{
.release = obj_test_release,
.sysfs_ops = &obj_test_sysops,
.default_attrs = def_attrs,
};
//Kset
int kset_filter(struct kset *kset, struct kobject *kobj)
{
printk("[call kset_filter (kobj->name = %s)]\n", kobj->name);
return 1;
}
const char *kset_name(struct kset *kset, struct kobject *kobj)
{
static char buf[20];
printk("[call kset_name (kobj->name = %s)]\n", kobj->name);
sprintf(buf, "%s", "New Kset Name");
return buf;
}
int kset_uevent(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env)
{
int i = 0;
printk("[uevent: %s]\n", kobj->name);
while( i < env->envp_idx)
{
printk("[envp[%d]: %s]\n", i, env->envp[i]);
i++;
}
return 0;
}
struct kset_uevent_ops uevent_ops =
{
.filter = kset_filter,
.name = kset_name,
.uevent = kset_uevent,
};
static int sysfs_test_init(void)
{
int ret = 0;
printk("[call sysfs_test_init.]\n");
kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);
kobject_set_name(&kset_c.kobj, "kset_c");
kset_c.kobj.kset = kset_p;
kset_c.kobj.ktype = &ktype;
ret = kset_register(&kset_c);
if(ret)
goto err1;
kobj.kset = kset_p;
ret = kobject_init_and_add(&kobj, &ktype, NULL, "kobj");
if(ret)
goto err;
strcpy(attrstr, "kobject attribute string");
return 0;
err:
kset_unregister(&kset_c);
err1:
kset_unregister(kset_p);
return ret;
}
static int sysfs_test_exit(void)
{
printk("[call sysfs_test_exit.]\n");
kset_unregister(kset_p);
kset_unregister(&kset_c);
kobject_del(&kobj);
return 0;
}
module_init(sysfs_test_init);
module_exit(sysfs_test_exit);
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
#include <linux/kobject.h>
MODULE_AUTHOR("STONE");
MODULE_LICENSE("GPL");
struct kset *kset_p;
struct kset kset_c;
struct kobject kobj;
char attrstr[256];
//kobject
struct attribute attr_str = {
.name = "attr_str",
.mode = S_IRWXU,
};
struct attribute attr_name = {
.name = "attr_name",
.mode = S_IRUSR,
};
static struct attribute *def_attrs[] = {
&attr_str,
&attr_name,
NULL,
};
void obj_test_release(struct kobject *kobject)
{
printk("[call obj_test_release]\n");
}
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr, char* buf)
{
if( !strcmp(attr->name, "attr_str") )
sprintf(buf, "1: %s\n", attrstr);
else
sprintf(buf, "2: %s\n", attr->name);
return strlen(buf);
}
ssize_t kobj_test_store(struct kobject *kobject, struct attribute *attr, const char* buf, size_t count)
{
if( !strcmp(attr->name, "attr_str") )
sprintf(attrstr, "%s", buf);
return count;
}
struct sysfs_ops obj_test_sysops =
{
.show = kobj_test_show,
.store = kobj_test_store,
};
struct kobj_type ktype =
{
.release = obj_test_release,
.sysfs_ops = &obj_test_sysops,
.default_attrs = def_attrs,
};
//Kset
int kset_filter(struct kset *kset, struct kobject *kobj)
{
printk("[call kset_filter (kobj->name = %s)]\n", kobj->name);
return 1;
}
const char *kset_name(struct kset *kset, struct kobject *kobj)
{
static char buf[20];
printk("[call kset_name (kobj->name = %s)]\n", kobj->name);
sprintf(buf, "%s", "New Kset Name");
return buf;
}
int kset_uevent(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env)
{
int i = 0;
printk("[uevent: %s]\n", kobj->name);
while( i < env->envp_idx)
{
printk("[envp[%d]: %s]\n", i, env->envp[i]);
i++;
}
return 0;
}
struct kset_uevent_ops uevent_ops =
{
.filter = kset_filter,
.name = kset_name,
.uevent = kset_uevent,
};
static int sysfs_test_init(void)
{
int ret = 0;
printk("[call sysfs_test_init.]\n");
kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);
kobject_set_name(&kset_c.kobj, "kset_c");
kset_c.kobj.kset = kset_p;
kset_c.kobj.ktype = &ktype;
ret = kset_register(&kset_c);
if(ret)
goto err1;
kobj.kset = kset_p;
ret = kobject_init_and_add(&kobj, &ktype, NULL, "kobj");
if(ret)
goto err;
strcpy(attrstr, "kobject attribute string");
return 0;
err:
kset_unregister(&kset_c);
err1:
kset_unregister(kset_p);
return ret;
}
static int sysfs_test_exit(void)
{
printk("[call sysfs_test_exit.]\n");
kset_unregister(kset_p);
kset_unregister(&kset_c);
kobject_del(&kobj);
return 0;
}
module_init(sysfs_test_init);
module_exit(sysfs_test_exit);
该模块安装后在/sys下的目录结构是这样的
/sys/kset_p/
├── kobj
│ ├── attr_name
│ └── attr_str
└── kset_c
├── attr_name
└── attr_str