Linux-2.6设备模型与sysfs文件系统

kobject对象:

    它是设备模型的基本结构,对应于sysfs文件系统中的一个目录,它是一个结构体,不过在Linux中引入了面向对象的思想,从某些角度,也可以看成是一个类。kobject对象通常被嵌入到其他的结构中,从面向对象的观点看,kobject可以看成是基类,而其他类都是派生的产物。

 

一个kobject的例子

/*

 * Sample kobject implementation

 *

 * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>

 * Copyright (C) 2007 Novell Inc.

 *

 * Released under the GPL version 2 only.

 *

 */

#include <linux/kobject.h>

#include <linux/string.h>

#include <linux/sysfs.h>

#include <linux/module.h>

#include <linux/init.h>

 

/*

 * This module shows how to create a simple subdirectory in sysfs called

 * /sys/kernel/kobject-example  In that directory, 3 files are created:

 * "foo", "baz", and "bar".  If an integer is written to these files, it can be

 * later read out of it.

 */

 

static int foo;

static int baz;

static int bar;

 

/*

 * The "foo" file where a static variable is read from and written to.

 */

static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,

         char *buf)

{

   return sprintf(buf, "%d\n", foo);

}

 

static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,

          const char *buf, size_t count)

{

   sscanf(buf, "%du", &foo);

   return count;

}

 

static struct kobj_attribute foo_attribute =

   __ATTR(foo, 0666, foo_show, foo_store);

 

/*

 * More complex function where we determine which varible is being accessed by

 * looking at the attribute for the "baz" and "bar" files.

 */

static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,

            char *buf)

{

   int var;

 

   if (strcmp(attr->attr.name, "baz") == 0)

      var = baz;

   else

      var = bar;

   return sprintf(buf, "%d\n", var);

}

 

static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,

             const char *buf, size_t count)

{

   int var;

 

   sscanf(buf, "%du", &var);

   if (strcmp(attr->attr.name, "baz") == 0)

      baz = var;

   else

      bar = var;

   return count;

}

 

static struct kobj_attribute baz_attribute =

   __ATTR(baz, 0666, b_show, b_store);

static struct kobj_attribute bar_attribute =

   __ATTR(bar, 0666, b_show, b_store);

 

 

/*

 * Create a group of attributes so that we can create and destory them all

 * at once.

 */

static struct attribute *attrs[] = {

   &foo_attribute.attr,

   &baz_attribute.attr,

   &bar_attribute.attr,

   NULL, /* need to NULL terminate the list of attributes */

};

 

/*

 * An unnamed attribute group will put all of the attributes directly in

 * the kobject directory.  If we specify a name, a subdirectory will be

 * created for the attributes with the directory being the name of the

 * attribute group.

 */

static struct attribute_group attr_group = {

   .attrs = attrs,

};

 

static struct kobject *example_kobj;

 

static int example_init(void)

{

   int retval;

 

   /*

    * Create a simple kobject with the name of "kobject_example",

    * located under /sys/kernel/

    *

    * As this is a simple directory, no uevent will be sent to

    * userspace.  That is why this function should not be used for

    * any type of dynamic kobjects, where the name and number are

    * not known ahead of time.

    */

   example_kobj = kobject_create_and_add("kobject_example", kernel_kobj);

   if (!example_kobj)

      return -ENOMEM;

 

   /* Create the files associated with this kobject */

   retval = sysfs_create_group(example_kobj, &attr_group);

   if (retval)

      kobject_put(example_kobj);

 

   return retval;

}

 

static void example_exit(void)

{

   kobject_put(example_kobj);

}

 

module_init(example_init);

module_exit(example_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");

该程序在/sys/kernel/下创建了一个目录,名为kobject-example, 在kobject-example目录下分别对应了三个文件bar, baz, foo, 分别对应着三个变量。

 

kset

kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,在内核中用kset数据结构表示。

kset例子

/*

 * Sample kset and ktype implementation

 *

 * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>

 * Copyright (C) 2007 Novell Inc.

 *

 * Released under the GPL version 2 only.

 *

 */

 

#include <linux/kobject.h>

#include <linux/string.h>

#include <linux/sysfs.h>

#include <linux/module.h>

#include <linux/init.h>

 

/*

 * This module shows how to create a kset in sysfs called

 * /sys/kernel/kset-example

 * Then tree kobjects are created and assigned to this kset, "foo", "baz",

 * and "bar".  In those kobjects, attributes of the same name are also

 * created and if an integer is written to these files, it can be later

 * read out of it.

 */

 

 

/*

 * This is our "object" that we will create a few of and register them with

 * sysfs.

 */

struct foo_obj {

   struct kobject kobj;

   int foo;

   int baz;

   int bar;

};

#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)

 

/* a custom attribute that works just for a struct foo_obj. */

struct foo_attribute {

   struct attribute attr;

   ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);

   ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);

};

#define to_foo_attr(x) container_of(x, struct foo_attribute, attr)

 

/*

 * The default show function that must be passed to sysfs.  This will be

 * called by sysfs for whenever a show function is called by the user on a

 * sysfs file associated with the kobjects we have registered.  We need to

 * transpose back from a "default" kobject to our custom struct foo_obj and

 * then call the show function for that specific object.

 */

static ssize_t foo_attr_show(struct kobject *kobj,

              struct attribute *attr,

              char *buf)

{

   struct foo_attribute *attribute;

   struct foo_obj *foo;

 

   attribute = to_foo_attr(attr);

   foo = to_foo_obj(kobj);

 

   if (!attribute->show)

      return -EIO;

 

   return attribute->show(foo, attribute, buf);

}

 

/*

 * Just like the default show function above, but this one is for when the

 * sysfs "store" is requested (when a value is written to a file.)

 */

static ssize_t foo_attr_store(struct kobject *kobj,

               struct attribute *attr,

               const char *buf, size_t len)

{

   struct foo_attribute *attribute;

   struct foo_obj *foo;

 

   attribute = to_foo_attr(attr);

   foo = to_foo_obj(kobj);

 

   if (!attribute->store)

      return -EIO;

 

   return attribute->store(foo, attribute, buf, len);

}

 

/* Our custom sysfs_ops that we will associate with our ktype later on */

static struct sysfs_ops foo_sysfs_ops = {

   .show = foo_attr_show,

   .store = foo_attr_store,

};

 

/*

 * The release function for our object.  This is REQUIRED by the kernel to

 * have.  We free the memory held in our object here.

 *

 * NEVER try to get away with just a "blank" release function to try to be

 * smarter than the kernel.  Turns out, no one ever is...

 */

static void foo_release(struct kobject *kobj)

{

   struct foo_obj *foo;

 

   foo = to_foo_obj(kobj);

   kfree(foo);

}

 

/*

 * The "foo" file where the .foo variable is read from and written to.

 */

static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,

         char *buf)

{

   return sprintf(buf, "%d\n", foo_obj->foo);

}

 

static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,

          const char *buf, size_t count)

{

   sscanf(buf, "%du", &foo_obj->foo);

   return count;

}

 

static struct foo_attribute foo_attribute =

   __ATTR(foo, 0666, foo_show, foo_store);

 

/*

 * More complex function where we determine which varible is being accessed by

 * looking at the attribute for the "baz" and "bar" files.

 */

static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,

            char *buf)

{

   int var;

 

   if (strcmp(attr->attr.name, "baz") == 0)

      var = foo_obj->baz;

   else

      var = foo_obj->bar;

   return sprintf(buf, "%d\n", var);

}

 

static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,

             const char *buf, size_t count)

{

   int var;

 

   sscanf(buf, "%du", &var);

   if (strcmp(attr->attr.name, "baz") == 0)

      foo_obj->baz = var;

   else

      foo_obj->bar = var;

   return count;

}

 

static struct foo_attribute baz_attribute =

   __ATTR(baz, 0666, b_show, b_store);

static struct foo_attribute bar_attribute =

   __ATTR(bar, 0666, b_show, b_store);

 

/*

 * Create a group of attributes so that we can create and destory them all

 * at once.

 */

static struct attribute *foo_default_attrs[] = {

   &foo_attribute.attr,

   &baz_attribute.attr,

   &bar_attribute.attr,

   NULL, /* need to NULL terminate the list of attributes */

};

 

/*

 * Our own ktype for our kobjects.  Here we specify our sysfs ops, the

 * release function, and the set of default attributes we want created

 * whenever a kobject of this type is registered with the kernel.

 */

static struct kobj_type foo_ktype = {

   .sysfs_ops = &foo_sysfs_ops,

   .release = foo_release,

   .default_attrs = foo_default_attrs,

};

 

static struct kset *example_kset;

static struct foo_obj *foo_obj;

static struct foo_obj *bar_obj;

static struct foo_obj *baz_obj;

 

static struct foo_obj *create_foo_obj(const char *name)

{

   struct foo_obj *foo;

   int retval;

 

   /* allocate the memory for the whole object */

   foo = kzalloc(sizeof(*foo), GFP_KERNEL);

   if (!foo)

      return NULL;

 

   /*

    * As we have a kset for this kobject, we need to set it before calling

    * the kobject core.

    */

   foo->kobj.kset = example_kset;

 

   /*

    * Initialize and add the kobject to the kernel.  All the default files

    * will be created here.  As we have already specified a kset for this

    * kobject, we don't have to set a parent for the kobject, the kobject

    * will be placed beneath that kset automatically.

    */

   retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);

   if (retval) {

      kfree(foo);

      return NULL;

   }

 

   /*

    * We are always responsible for sending the uevent that the kobject

    * was added to the system.

    */

   kobject_uevent(&foo->kobj, KOBJ_ADD);

 

   return foo;

}

 

static void destroy_foo_obj(struct foo_obj *foo)

{

   kobject_put(&foo->kobj);

}

 

static int example_init(void)

{

   /*

    * Create a kset with the name of "kset_example",

    * located under /sys/kernel/

    */

   example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);

   if (!example_kset)

      return -ENOMEM;

 

   /*

    * Create three objects and register them with our kset

    */

   foo_obj = create_foo_obj("foo");

   if (!foo_obj)

      goto foo_error;

 

   bar_obj = create_foo_obj("bar");

   if (!bar_obj)

      goto bar_error;

 

   baz_obj = create_foo_obj("baz");

   if (!baz_obj)

      goto baz_error;

 

   return 0;

 

baz_error:

   destroy_foo_obj(bar_obj);

bar_error:

   destroy_foo_obj(foo_obj);

foo_error:

   return -EINVAL;

}

 

static void example_exit(void)

{

   destroy_foo_obj(baz_obj);

   destroy_foo_obj(bar_obj);

   destroy_foo_obj(foo_obj);

   kset_unregister(example_kset);

}

 

module_init(example_init);

module_exit(example_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");

该程序在/sys/kernel/下创建了一个目录,名为kset-example, 在kset-example目录下分别对应了三个子目录bar, baz, foo, 里面又有三个文件 ,分别对应着三个变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值