summaryrefslogtreecommitdiff
path: root/Documentation/kobject.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/kobject.txt')
-rw-r--r--Documentation/kobject.txt489
1 files changed, 293 insertions, 196 deletions
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index ca86a885ad8f..bf3256e04027 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -1,289 +1,386 @@
-The kobject Infrastructure
+Everything you never wanted to know about kobjects, ksets, and ktypes
-Patrick Mochel <mochel@osdl.org>
+Greg Kroah-Hartman <gregkh@suse.de>
-Updated: 3 June 2003
+Based on an original article by Jon Corbet for lwn.net written October 1,
+2003 and located at http://lwn.net/Articles/51437/
+Last updated December 19, 2007
-Copyright (c) 2003 Patrick Mochel
-Copyright (c) 2003 Open Source Development Labs
+Part of the difficulty in understanding the driver model - and the kobject
+abstraction upon which it is built - is that there is no obvious starting
+place. Dealing with kobjects requires understanding a few different types,
+all of which make reference to each other. In an attempt to make things
+easier, we'll take a multi-pass approach, starting with vague terms and
+adding detail as we go. To that end, here are some quick definitions of
+some terms we will be working with.
-0. Introduction
+ - A kobject is an object of type struct kobject. Kobjects have a name
+ and a reference count. A kobject also has a parent pointer (allowing
+ objects to be arranged into hierarchies), a specific type, and,
+ usually, a representation in the sysfs virtual filesystem.
-The kobject infrastructure performs basic object management that larger
-data structures and subsystems can leverage, rather than reimplement
-similar functionality. This functionality primarily concerns:
+ Kobjects are generally not interesting on their own; instead, they are
+ usually embedded within some other structure which contains the stuff
+ the code is really interested in.
-- Object reference counting.
-- Maintaining lists (sets) of objects.
-- Object set locking.
-- Userspace representation.
+ No structure should EVER have more than one kobject embedded within it.
+ If it does, the reference counting for the object is sure to be messed
+ up and incorrect, and your code will be buggy. So do not do this.
-The infrastructure consists of a number of object types to support
-this functionality. Their programming interfaces are described below
-in detail, and briefly here:
+ - A ktype is the type of object that embeds a kobject. Every structure
+ that embeds a kobject needs a corresponding ktype. The ktype controls
+ what happens to the kobject when it is created and destroyed.
-- kobjects a simple object.
-- kset a set of objects of a certain type.
-- ktype a set of helpers for objects of a common type.
+ - A kset is a group of kobjects. These kobjects can be of the same ktype
+ or belong to different ktypes. The kset is the basic container type for
+ collections of kobjects. Ksets contain their own kobjects, but you can
+ safely ignore that implementation detail as the kset core code handles
+ this kobject automatically.
+ When you see a sysfs directory full of other directories, generally each
+ of those directories corresponds to a kobject in the same kset.
-The kobject infrastructure maintains a close relationship with the
-sysfs filesystem. Each kobject that is registered with the kobject
-core receives a directory in sysfs. Attributes about the kobject can
-then be exported. Please see Documentation/filesystems/sysfs.txt for
-more information.
+We'll look at how to create and manipulate all of these types. A bottom-up
+approach will be taken, so we'll go back to kobjects.
-The kobject infrastructure provides a flexible programming interface,
-and allows kobjects and ksets to be used without being registered
-(i.e. with no sysfs representation). This is also described later.
+Embedding kobjects
-1. kobjects
+It is rare for kernel code to create a standalone kobject, with one major
+exception explained below. Instead, kobjects are used to control access to
+a larger, domain-specific object. To this end, kobjects will be found
+embedded in other structures. If you are used to thinking of things in
+object-oriented terms, kobjects can be seen as a top-level, abstract class
+from which other classes are derived. A kobject implements a set of
+capabilities which are not particularly useful by themselves, but which are
+nice to have in other objects. The C language does not allow for the
+direct expression of inheritance, so other techniques - such as structure
+embedding - must be used.
-1.1 Description
+So, for example, the UIO code has a structure that defines the memory
+region associated with a uio device:
+struct uio_mem {
+ struct kobject kobj;
+ unsigned long addr;
+ unsigned long size;
+ int memtype;
+ void __iomem *internal_addr;
+};
-struct kobject is a simple data type that provides a foundation for
-more complex object types. It provides a set of basic fields that
-almost all complex data types share. kobjects are intended to be
-embedded in larger data structures and replace fields they duplicate.
+If you have a struct uio_mem structure, finding its embedded kobject is
+just a matter of using the kobj member. Code that works with kobjects will
+often have the opposite problem, however: given a struct kobject pointer,
+what is the pointer to the containing structure? You must avoid tricks
+(such as assuming that the kobject is at the beginning of the structure)
+and, instead, use the container_of() macro, found in <linux/kernel.h>:
-1.2 Definition
+ container_of(pointer, type, member)
-struct kobject {
- const char * k_name;
- struct kref kref;
- struct list_head entry;
- struct kobject * parent;
- struct kset * kset;
- struct kobj_type * ktype;
- struct sysfs_dirent * sd;
- wait_queue_head_t poll;
-};
+where pointer is the pointer to the embedded kobject, type is the type of
+the containing structure, and member is the name of the structure field to
+which pointer points. The return value from container_of() is a pointer to
+the given type. So, for example, a pointer "kp" to a struct kobject
+embedded within a struct uio_mem could be converted to a pointer to the
+containing uio_mem structure with:
-void kobject_init(struct kobject *);
-int kobject_add(struct kobject *);
-int kobject_register(struct kobject *);
+ struct uio_mem *u_mem = container_of(kp, struct uio_mem, kobj);
-void kobject_del(struct kobject *);
-void kobject_unregister(struct kobject *);
+Programmers often define a simple macro for "back-casting" kobject pointers
+to the containing type.
-struct kobject * kobject_get(struct kobject *);
-void kobject_put(struct kobject *);
+Initialization of kobjects
-1.3 kobject Programming Interface
+Code which creates a kobject must, of course, initialize that object. Some
+of the internal fields are setup with a (mandatory) call to kobject_init():
-kobjects may be dynamically added and removed from the kobject core
-using kobject_register() and kobject_unregister(). Registration
-includes inserting the kobject in the list of its dominant kset and
-creating a directory for it in sysfs.
+ void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
-Alternatively, one may use a kobject without adding it to its kset's list
-or exporting it via sysfs, by simply calling kobject_init(). An
-initialized kobject may later be added to the object hierarchy by
-calling kobject_add(). An initialized kobject may be used for
-reference counting.
+The ktype is required for a kobject to be created properly, as every kobject
+must have an associated kobj_type. After calling kobject_init(), to
+register the kobject with sysfs, the function kobject_add() must be called:
-Note: calling kobject_init() then kobject_add() is functionally
-equivalent to calling kobject_register().
+ int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
-When a kobject is unregistered, it is removed from its kset's list,
-removed from the sysfs filesystem, and its reference count is decremented.
-List and sysfs removal happen in kobject_del(), and may be called
-manually. kobject_put() decrements the reference count, and may also
-be called manually.
+This sets up the parent of the kobject and the name for the kobject
+properly. If the kobject is to be associated with a specific kset,
+kobj->kset must be assigned before calling kobject_add(). If a kset is
+associated with a kobject, then the parent for the kobject can be set to
+NULL in the call to kobject_add() and then the kobject's parent will be the
+kset itself.
-A kobject's reference count may be incremented with kobject_get(),
-which returns a valid reference to a kobject; and decremented with
-kobject_put(). An object's reference count may only be incremented if
-it is already positive.
+As the name of the kobject is set when it is added to the kernel, the name
+of the kobject should never be manipulated directly. If you must change
+the name of the kobject, call kobject_rename():
-When a kobject's reference count reaches 0, the method struct
-kobj_type::release() (which the kobject's kset points to) is called.
-This allows any memory allocated for the object to be freed.
+ int kobject_rename(struct kobject *kobj, const char *new_name);
+There is a function called kobject_set_name() but that is legacy cruft and
+is being removed. If your code needs to call this function, it is
+incorrect and needs to be fixed.
-NOTE!!!
+To properly access the name of the kobject, use the function
+kobject_name():
-It is _imperative_ that you supply a destructor for dynamically
-allocated kobjects to free them if you are using kobject reference
-counts. The reference count controls the lifetime of the object.
-If it goes to 0, then it is assumed that the object will
-be freed and cannot be used.
+ const char *kobject_name(const struct kobject * kobj);
-More importantly, you must free the object there, and not immediately
-after an unregister call. If someone else is referencing the object
-(e.g. through a sysfs file), they will obtain a reference to the
-object, assume it's valid and operate on it. If the object is
-unregistered and freed in the meantime, the operation will then
-reference freed memory and go boom.
+There is a helper function to both initialize and add the kobject to the
+kernel at the same time, called supprisingly enough kobject_init_and_add():
-This can be prevented, in the simplest case, by defining a release
-method and freeing the object from there only. Note that this will not
-secure reference count/object management models that use a dual
-reference count or do other wacky things with the reference count
-(like the networking layer).
+ int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
+ struct kobject *parent, const char *fmt, ...);
+The arguments are the same as the individual kobject_init() and
+kobject_add() functions described above.
-1.4 sysfs
-Each kobject receives a directory in sysfs. This directory is created
-under the kobject's parent directory.
+Uevents
-If a kobject does not have a parent when it is registered, its parent
-becomes its dominant kset.
+After a kobject has been registered with the kobject core, you need to
+announce to the world that it has been created. This can be done with a
+call to kobject_uevent():
-If a kobject does not have a parent nor a dominant kset, its directory
-is created at the top-level of the sysfs partition.
+ int kobject_uevent(struct kobject *kobj, enum kobject_action action);
+Use the KOBJ_ADD action for when the kobject is first added to the kernel.
+This should be done only after any attributes or children of the kobject
+have been initialized properly, as userspace will instantly start to look
+for them when this call happens.
+When the kobject is removed from the kernel (details on how to do that is
+below), the uevent for KOBJ_REMOVE will be automatically created by the
+kobject core, so the caller does not have to worry about doing that by
+hand.
-2. ksets
-2.1 Description
+Reference counts
-A kset is a set of kobjects that are embedded in the same type.
+One of the key functions of a kobject is to serve as a reference counter
+for the object in which it is embedded. As long as references to the object
+exist, the object (and the code which supports it) must continue to exist.
+The low-level functions for manipulating a kobject's reference counts are:
+ struct kobject *kobject_get(struct kobject *kobj);
+ void kobject_put(struct kobject *kobj);
-struct kset {
- struct kobj_type * ktype;
- struct list_head list;
- struct kobject kobj;
- struct kset_uevent_ops * uevent_ops;
-};
+A successful call to kobject_get() will increment the kobject's reference
+counter and return the pointer to the kobject.
+When a reference is released, the call to kobject_put() will decrement the
+reference count and, possibly, free the object. Note that kobject_init()
+sets the reference count to one, so the code which sets up the kobject will
+need to do a kobject_put() eventually to release that reference.
-void kset_init(struct kset * k);
-int kset_add(struct kset * k);
-int kset_register(struct kset * k);
-void kset_unregister(struct kset * k);
+Because kobjects are dynamic, they must not be declared statically or on
+the stack, but instead, always allocated dynamically. Future versions of
+the kernel will contain a run-time check for kobjects that are created
+statically and will warn the developer of this improper usage.
-struct kset * kset_get(struct kset * k);
-void kset_put(struct kset * k);
+If all that you want to use a kobject for is to provide a reference counter
+for your structure, please use the struct kref instead; a kobject would be
+overkill. For more information on how to use struct kref, please see the
+file Documentation/kref.txt in the Linux kernel source tree.
-struct kobject * kset_find_obj(struct kset *, char *);
+Creating "simple" kobjects
-The type that the kobjects are embedded in is described by the ktype
-pointer.
+Sometimes all that a developer wants is a way to create a simple directory
+in the sysfs hierarchy, and not have to mess with the whole complication of
+ksets, show and store functions, and other details. This is the one
+exception where a single kobject should be created. To create such an
+entry, use the function:
-A kset contains a kobject itself, meaning that it may be registered in
-the kobject hierarchy and exported via sysfs. More importantly, the
-kset may be embedded in a larger data type, and may be part of another
-kset (of that object type).
+ struct kobject *kobject_create_and_add(char *name, struct kobject *parent);
-For example, a block device is an object (struct gendisk) that is
-contained in a set of block devices. It may also contain a set of
-partitions (struct hd_struct) that have been found on the device. The
-following code snippet illustrates how to express this properly.
+This function will create a kobject and place it in sysfs in the location
+underneath the specified parent kobject. To create simple attributes
+associated with this kobject, use:
- struct gendisk * disk;
- ...
- disk->kset.kobj.kset = &block_kset;
- disk->kset.ktype = &partition_ktype;
- kset_register(&disk->kset);
+ int sysfs_create_file(struct kobject *kobj, struct attribute *attr);
+or
+ int sysfs_create_group(struct kobject *kobj, struct attribute_group *grp);
-- The kset that the disk's embedded object belongs to is the
- block_kset, and is pointed to by disk->kset.kobj.kset.
+Both types of attributes used here, with a kobject that has been created
+with the kobject_create_and_add(), can be of type kobj_attribute, so no
+special custom attribute is needed to be created.
-- The type of objects on the disk's _subordinate_ list are partitions,
- and is set in disk->kset.ktype.
+See the example module, samples/kobject/kobject-example.c for an
+implementation of a simple kobject and attributes.
-- The kset is then registered, which handles initializing and adding
- the embedded kobject to the hierarchy.
-2.2 kset Programming Interface
+ktypes and release methods
-All kset functions, except kset_find_obj(), eventually forward the
-calls to their embedded kobjects after performing kset-specific
-operations. ksets offer a similar programming model to kobjects: they
-may be used after they are initialized, without registering them in
-the hierarchy.
+One important thing still missing from the discussion is what happens to a
+kobject when its reference count reaches zero. The code which created the
+kobject generally does not know when that will happen; if it did, there
+would be little point in using a kobject in the first place. Even
+predictable object lifecycles become more complicated when sysfs is brought
+in as other portions of the kernel can get a reference on any kobject that
+is registered in the system.
-kset_find_obj() may be used to locate a kobject with a particular
-name. The kobject, if found, is returned.
+The end result is that a structure protected by a kobject cannot be freed
+before its reference count goes to zero. The reference count is not under
+the direct control of the code which created the kobject. So that code must
+be notified asynchronously whenever the last reference to one of its
+kobjects goes away.
-There are also some helper functions which names point to the formerly
-existing "struct subsystem", whose functions have been taken over by
-ksets.
+Once you registered your kobject via kobject_add(), you must never use
+kfree() to free it directly. The only safe way is to use kobject_put(). It
+is good practice to always use kobject_put() after kobject_init() to avoid
+errors creeping in.
+This notification is done through a kobject's release() method. Usually
+such a method has a form like:
-decl_subsys(name,type,uevent_ops)
+ void my_object_release(struct kobject *kobj)
+ {
+ struct my_object *mine = container_of(kobj, struct my_object, kobj);
-Declares a kset named '<name>_subsys' of type <type> with
-uevent_ops <uevent_ops>. For example,
+ /* Perform any additional cleanup on this object, then... */
+ kfree(mine);
+ }
-decl_subsys(devices, &ktype_device, &device_uevent_ops);
+One important point cannot be overstated: every kobject must have a
+release() method, and the kobject must persist (in a consistent state)
+until that method is called. If these constraints are not met, the code is
+flawed. Note that the kernel will warn you if you forget to provide a
+release() method. Do not try to get rid of this warning by providing an
+"empty" release function; you will be mocked mercilessly by the kobject
+maintainer if you attempt this.
-is equivalent to doing:
+Note, the name of the kobject is available in the release function, but it
+must NOT be changed within this callback. Otherwise there will be a memory
+leak in the kobject core, which makes people unhappy.
-struct kset devices_subsys = {
- .ktype = &ktype_devices,
- .uevent_ops = &device_uevent_ops,
-};
-kobject_set_name(&devices_subsys, name);
+Interestingly, the release() method is not stored in the kobject itself;
+instead, it is associated with the ktype. So let us introduce struct
+kobj_type:
+
+ struct kobj_type {
+ void (*release)(struct kobject *);
+ struct sysfs_ops *sysfs_ops;
+ struct attribute **default_attrs;
+ };
-The objects that are registered with a subsystem that use the
-subsystem's default list must have their kset ptr set properly. These
-objects may have embedded kobjects or ksets. The
-following helper makes setting the kset easier:
+This structure is used to describe a particular type of kobject (or, more
+correctly, of containing object). Every kobject needs to have an associated
+kobj_type structure; a pointer to that structure must be specified when you
+call kobject_init() or kobject_init_and_add().
+The release field in struct kobj_type is, of course, a pointer to the
+release() method for this type of kobject. The other two fields (sysfs_ops
+and default_attrs) control how objects of this type are represented in
+sysfs; they are beyond the scope of this document.
-kobj_set_kset_s(obj,subsys)
+The default_attrs pointer is a list of default attributes that will be
+automatically created for any kobject that is registered with this ktype.
-- Assumes that obj->kobj exists, and is a struct kobject.
-- Sets the kset of that kobject to the kset <subsys>.
-int subsystem_register(struct kset *s);
-void subsystem_unregister(struct kset *s);
+ksets
-These are just wrappers around the respective kset_* functions.
+A kset is merely a collection of kobjects that want to be associated with
+each other. There is no restriction that they be of the same ktype, but be
+very careful if they are not.
-2.3 sysfs
+A kset serves these functions:
-ksets are represented in sysfs when their embedded kobjects are
-registered. They follow the same rules of parenting, with one
-exception. If a kset does not have a parent, nor is its embedded
-kobject part of another kset, the kset's parent becomes its dominant
-subsystem.
+ - It serves as a bag containing a group of objects. A kset can be used by
+ the kernel to track "all block devices" or "all PCI device drivers."
-If the kset does not have a parent, its directory is created at the
-sysfs root. This should only happen when the kset registered is
-embedded in a subsystem itself.
+ - A kset is also a subdirectory in sysfs, where the associated kobjects
+ with the kset can show up. Every kset contains a kobject which can be
+ set up to be the parent of other kobjects; the top-level directories of
+ the sysfs hierarchy are constructed in this way.
+ - Ksets can support the "hotplugging" of kobjects and influence how
+ uevent events are reported to user space.
-3. struct ktype
+In object-oriented terms, "kset" is the top-level container class; ksets
+contain their own kobject, but that kobject is managed by the kset code and
+should not be manipulated by any other user.
-3.1. Description
+A kset keeps its children in a standard kernel linked list. Kobjects point
+back to their containing kset via their kset field. In almost all cases,
+the kobjects belonging to a ket have that kset (or, strictly, its embedded
+kobject) in their parent.
-struct kobj_type {
- void (*release)(struct kobject *);
- struct sysfs_ops * sysfs_ops;
- struct attribute ** default_attrs;
+As a kset contains a kobject within it, it should always be dynamically
+created and never declared statically or on the stack. To create a new
+kset use:
+ struct kset *kset_create_and_add(const char *name,
+ struct kset_uevent_ops *u,
+ struct kobject *parent);
+
+When you are finished with the kset, call:
+ void kset_unregister(struct kset *kset);
+to destroy it.
+
+An example of using a kset can be seen in the
+samples/kobject/kset-example.c file in the kernel tree.
+
+If a kset wishes to control the uevent operations of the kobjects
+associated with it, it can use the struct kset_uevent_ops to handle it:
+
+struct kset_uevent_ops {
+ int (*filter)(struct kset *kset, struct kobject *kobj);
+ const char *(*name)(struct kset *kset, struct kobject *kobj);
+ int (*uevent)(struct kset *kset, struct kobject *kobj,
+ struct kobj_uevent_env *env);
};
-Object types require specific functions for converting between the
-generic object and the more complex type. struct kobj_type provides
-the object-specific fields, which include:
+The filter function allows a kset to prevent a uevent from being emitted to
+userspace for a specific kobject. If the function returns 0, the uevent
+will not be emitted.
+
+The name function will be called to override the default name of the kset
+that the uevent sends to userspace. By default, the name will be the same
+as the kset itself, but this function, if present, can override that name.
+
+The uevent function will be called when the uevent is about to be sent to
+userspace to allow more environment variables to be added to the uevent.
+
+One might ask how, exactly, a kobject is added to a kset, given that no
+functions which perform that function have been presented. The answer is
+that this task is handled by kobject_add(). When a kobject is passed to
+kobject_add(), its kset member should point to the kset to which the
+kobject will belong. kobject_add() will handle the rest.
+
+If the kobject belonging to a kset has no parent kobject set, it will be
+added to the kset's directory. Not all members of a kset do necessarily
+live in the kset directory. If an explicit parent kobject is assigned
+before the kobject is added, the kobject is registered with the kset, but
+added below the parent kobject.
+
+
+Kobject removal
-- release: Called when the kobject's reference count reaches 0. This
- should convert the object to the more complex type and free it.
+After a kobject has been registered with the kobject core successfully, it
+must be cleaned up when the code is finished with it. To do that, call
+kobject_put(). By doing this, the kobject core will automatically clean up
+all of the memory allocated by this kobject. If a KOBJ_ADD uevent has been
+sent for the object, a corresponding KOBJ_REMOVE uevent will be sent, and
+any other sysfs housekeeping will be handled for the caller properly.
-- sysfs_ops: Provides conversion functions for sysfs access. Please
- see the sysfs documentation for more information.
+If you need to do a two-stage delete of the kobject (say you are not
+allowed to sleep when you need to destroy the object), then call
+kobject_del() which will unregister the kobject from sysfs. This makes the
+kobject "invisible", but it is not cleaned up, and the reference count of
+the object is still the same. At a later time call kobject_put() to finish
+the cleanup of the memory associated with the kobject.
-- default_attrs: Default attributes to be exported via sysfs when the
- object is registered.Note that the last attribute has to be
- initialized to NULL ! You can find a complete implementation
- in block/genhd.c
+kobject_del() can be used to drop the reference to the parent object, if
+circular references are constructed. It is valid in some cases, that a
+parent objects references a child. Circular references _must_ be broken
+with an explicit call to kobject_del(), so that a release functions will be
+called, and the objects in the former circle release each other.
-Instances of struct kobj_type are not registered; only referenced by
-the kset. A kobj_type may be referenced by an arbitrary number of
-ksets, as there may be disparate sets of identical objects.
+Example code to copy from
+For a more complete example of using ksets and kobjects properly, see the
+sample/kobject/kset-example.c code.