Commit 351b11ab authored by Patrick Mochel's avatar Patrick Mochel

Update kobject documentation.

parent 33e86005
kobjects - Simple, Generic Kernel Objects The kobject Infrastructure
Patrick Mochel <mochel@osdl.org> Patrick Mochel <mochel@osdl.org>
30 October 2002 7 January 2003
0. Introduction
The kobject infrastructure performs basic object managment that larger
data structures and subsystems can leverage, rather than reimplement
similar functionality. This functionality consists primarily concerns:
- Object reference counting.
- Maintaining lists (sets) of objects.
- Object set locking.
- Userspace representation.
The infrastructure consists of a number of object types to support
this functionality. Their programming interfaces are described below
in detail, and briefly here:
- kobjects a simple object.
- kset a set of objects of a certain type.
- ktype a set of helpers for objects of a common type.
- subsystem a controlling object for a number of ksets.
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.
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.
1. kobjects 1. kobjects
1.1 Description 1.1 Description
struct kobject introduces a simple, intregral datatype and a simple
set of semantics for operating on the device. kobjects are intended to
be embedded in larger data structures and replace fields it
duplicates. A set of library functions has been developed to assist in
the manipulation of kobjects.
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 it duplicates.
1.2 Defintion 1.2 Defintion
struct kobject { struct kobject {
char name[16]; char name[KOBJ_NAME_LEN];
atomic_t refcount; atomic_t refcount;
struct list_head entry; struct list_head entry;
struct kobject * parent; struct kobject * parent;
struct subsystem * subsys; struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry; struct dentry * dentry;
}; };
...@@ -32,204 +64,276 @@ int kobject_add(struct kobject *); ...@@ -32,204 +64,276 @@ int kobject_add(struct kobject *);
int kobject_register(struct kobject *); int kobject_register(struct kobject *);
void kobject_del(struct kobject *); void kobject_del(struct kobject *);
void kobject_cleanup(struct kobject *);
void kobject_unregister(struct kobject *); void kobject_unregister(struct kobject *);
struct kobject * kobject_get(struct kobject *); struct kobject * kobject_get(struct kobject *);
void kobject_put(struct kobject *); void kobject_put(struct kobject *);
1.3 kobject Programming Interface
2. subsystems 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.
2.1 Description Alternatively, one may use a kobject without adding 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.
struct subsystem is introduced to describe a collection of objects of Note: calling kobject_init(), then kobject_add() is functionally
a certain type. subsystems are kobjects themselves, though they equivalent to calling kobject_register().
contain lists of kobjects that belong to that subsystem. Objects of a
subsystem (the embedder objects in which kobjects live) are all of the
same type.
2.2 Definition When a kobject is unregistered, it is removed from its kset's list,
removed from the sysfs filesystem, and its reference 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.
struct subsystem { A kobject's reference count may be incremented with kobject_get(),
struct kobject kobj; 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.
When a kobject's reference count reaches 0, the method struct
ktype::release() (which the kobject's kset points to) is called. This
allows any memory allocated for the object to be freed.
1.4 sysfs
Each kobject receives a directory in sysfs. This directory is created
under the kobject's parent directory.
If a kobject does not have a parent when it is registered, its parent
becomes its dominant kset.
If a kobject does not have a parent nor a dominant kset, its directory
is created at the top-level of the sysfs partition. This should only
happen for kobjects that are embedded in a struct subsystem.
2. ksets
2.1 Desecription
A kset is a set of kobjects that are embedded in the same type.
struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list; struct list_head list;
struct rw_semaphore rwsem; struct kobject kobj;
struct subsystem * parent; };
void kset_init(struct kset * k);
int kset_add(struct kset * k);
int kset_register(struct kset * k);
void kset_unregister(struct kset * k);
struct kset * kset_get(struct kset * k);
void kset_put(struct kset * k);
struct kobject * kset_find_obj(struct kset *, char *);
The type that the kobjects are embedded in is described by the ktype
pointer. The subsystem that the kobject belongs to is pointed to by
subsys pointer.
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).
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 properly express this.
struct gendisk * disk;
...
disk->kset.kobj.kset = &block_kset;
disk->kset.ktype = &partition_ktype;
kset_register(&disk->kset);
- The kset that the disk's embedded object belongs to is the
block_kset, and is pointed to disk->kset.kobj.kset.
- The type of object of the disk's _subordinate_ list are partitions,
and is set in disk->kset.ktype.
- The kset is then registered, which handles initializing and adding
the embedded kobject to the hierarchy.
2.2 kset Programming Interface
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.
kset_find_obj() may be used to locate a kobject with a particular
name. The kobject, if found, is returned.
2.3 sysfs
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 it's dominant
subsystem.
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.
3. struct ktype
3.1. Description
struct kobj_type {
void (*release)(struct kobject *); void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops; struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs; struct attribute ** default_attrs;
}; };
void subsystem_init(struct subsystem *);
int subsystem_register(struct subsystem *);
void subsystem_unregister(struct subsystem *);
struct subsystem * subsys_get(struct subsystem * s); Object types require specific functions for converting between the
void subsys_put(struct subsystem * s); generic object and the more complex type. struct kobj_type provides
the object-specific fields, which include:
- release: Called when the kobject's reference count reaches 0. This
should convert the object to the more complex type and free it.
- sysfs_ops: Provides conversion functions for sysfs access. Please
see the sysfs documentation for more information.
- default_attrs: Default attributes to exported via sysfs when the
object is registered.
3. The Interface
The kobject API provides a symmeticral interface that may be used in Instances of struct kobj_type are not registered; only referenced by
one of two ways: by using the default front-end registration the kset. A kobj_type may be referenced by an arbitrary number of
interface, or by directly using the backend helpers the registration ksets, as their may be disparate sets of identical objects.
interface uses.
3.1 Default Usage
The default usage is to use kobjet_register() to add a device to the
object hierarchy, and kobject_unregister() to remove it.
kobject_register() will call kobject_init() and kobject_add() 4. subsystems
consecutively. kobject_init() will initialize the object and increment
the reference count of the subsystem the object belongs to. It will
leave the reference count of the object at 1.
kobject_add() will insert it into the object hierarchy and create 4.1 Description
a sysfs directory for the object. This will increment the reference
count of the object, leaving it at 2.
kobject_unregister() will call kobject_del() and kobject_put() A subsystem represents a significant entity of code that maintains an
consecutively. kobject_del() will remove the object from the hierarchy arbitrary number of sets of objects of various types. Since the number
and the sysfs directory for the object. It will decrement the of ksets, and the type of objects they contain, are variable, a
reference count for the object. Assuming there are no other users of generic representation of a subsystem is minimal.
the object, it will be left at 1.
kobject_put() will decrement the reference count of the object, and
when it reaches 0, call kobject_cleanup(). This will happen
immediately if there are no other users of the object.
kobject_cleanup() will call the subsystem's release() method
for the object, and decrement the subsystem's reference count.
Because kobject_unregister() calls kobject_put(), instead of struct subsystem {
kobject_cleanup() directly, when an object is unregistered, the struct kset kset;
pointer to the object is guaranteed to remain valid until the last struct rw_semaphore rwsem;
reference to the object has gone away. };
int subsystem_register(struct subsystem *);
void subsystem_unregister(struct subsystem *);
Users of objects should call kobject_get() to obtain a reference to struct subsystem * subsys_get(struct subsystem * s);
the object that they are using. If the object passed to it is a valid void subsys_put(struct subsystem * s);
object (i.e. still present in the system), it will return a pointer to
the object. Otherwise, it will return NULL.
When users are done using an object, they should call kobject_put() to
decrement the reference count on the object. As explained above, when
the reference count for the object reaches 0, kobject_cleanup() will
be called for the object.
A subsystem contains an embedded kset so:
3.2 Backend Usage - It can be represented in the object hierarchy via the kset's
embedded kobject.
Users of the kobject infrastructure may use the backend functions - It can maintain a default list of objects of one type.
directly. In order to maintain consistency and reduce confusion, users
of the interface should use only the front end registration-oriented
interface, or the backend helpers.
Using the backend helpers allows code to use the kobjects solely for Additional ksets may attach to the subsystem simply by referencing the
the reference counting and garbage collection mechanisms, and subsystem before they are registered. (This one-way reference means
optionally adding them to the object hierarchy or exporting them via that there is no way to determine the ksets that are attached to the
sysfs. subsystem.)
To take advantage of this side of the interface, users should call All ksets that are attached to a subsystem share the subsystem's R/W
kobject_init() to initialize the object. As stated above, this will semaphore.
leave the reference count of the object at 1, and will enable the
subsystem to use the reference count of the object.
When the life of the object is ending, the kobject_put() should be
called to decrement the reference count of the object. Just like
above, this will call kobject_cleanup() when the reference count
reaches 0, and release() method of the object's subsystem will be
called.
During the lifetime of the object, kobject_add() and kobject_del() may 4.2 Programming Interface.
be called to add the object to the hierarchy and export it via
sysfs. kobject_del() must always be called if kobject_add() has
previously been called. Care should be taken to ensure kobject_del()
is called before the final kobject_put() is called, though not doing
so will not cause catastrophe, only confusion when reading the source
code. Fatal results are avoided by having kobject_add() increment the
reference count of the object, for kobject_del() to decrement.
The subsystem programming interface is simple and does not offer the
flexibility that the kset and kobject programming interfaces do. They
may be registered and unregistered, as well as reference counted. Each
call forwards the calls to their embedded ksets (which forward the
calls to their embedded kobjects).
3.3 Summary
Using either interface, users should obtain the same results. The 4.3 Helpers
registration interface does the same actions as the backend interface,
though it guarantees that initialization and addition, and deletion
and cleanup, happen consecutively.
A number of macros are available to make dealing with subsystems, and
their embedded objects easier.
Familial Relations
kobjects and subsystems intersect and intertwine in several ways. Each decl_subsys(name,type)
is well-defined (though maybe they could be made simpler). Each kobject
belongs to a subsystem. Since subsystems are kobjects themselves, they
also belong to a controlling subsystem. This implies that subsystems
are hierarchial.
Many kobjects are hierarchial in nature, which is represented by Declares a subsystem named '<name>_subsys', with an embedded kset of
including a pointer to its parent kobject in struct kobject. Many type <type>. For example,
different types of kobject-embedding objects may all point to the same
parent.
The ancestral hierarchy of kobjects should not be confused with decl_subsys(devices,&ktype_devices);
membership in a subsystem, or the ancestral relationship of
subsystems. A set of kobjects may all belong to a subsystem, but all
have different parents.
kobjects may be orphans and have no explicit parent. In that case, the is equivalent to doing:
subsystem to which the object belongs becomes its parent.
struct subsystem device_subsys = {
.kset = {
.kobj = {
.name = "devices",
},
.ktype = &ktype_devices,
}
};
Sysfs
These rules force a complete kobject hierarchy, which Suprise! maps The objects that are registered with a subsystem that use the
very well onto a filesystem. subsystem's default list must have their kset ptr set properly. These
objects may have embedded kobjects, ksets, or other subsystems. The
following helpers make setting the kset easier:
driverfs was recently cloned, and there now exists sysfs. All driverfs
operations operate on a separate data type: struct driver_dir_entry,
which all objects that are represented in driverfs must have. driverfs
also allowed rogue directory creation that had no explicit objects
associated with them.
struct kobject is intended to be the common data type which sysfs kobj_set_kset_s(obj,subsys)
operates on. This gives the filesystem the ability to directly access
more fields of the object, including the reference count. This also
forces each directory in the filesystem to be tied directly to a
kobject.
- Assumes that obj->kobj exists, and is a struct kobject.
- Sets the kset of that kobject to the subsystem's embedded kset.
Directory Placement
Parental relationships are determined in the kobject/subsystem layer, kset_set_kset_s(obj,subsys)
and the kobject is then passed off to the sysfs layer. kobjects with
no parent have directories created for them in the sysfs root
directory. Per the rules above, the only kobjects that remain orphans
are subsystems without parent subsystems (since leaf objects either
have an explicit parent, or are assigned their controlling subsystem
as their foster parent).
- Assumes that obj->kset exists, and is a struct kset.
- Sets the kset of the embedded kobject to the subsystem's
embedded kset.
File Callbacks subsys_set_kset(obj,subsys)
Previously, each driverfs directory contained a pointer to a list of file - Assumes obj->subsys exists, and is a struct subsystem.
operations for reading and writing driverfs files. These callbacks - Sets obj->subsys.kset.kobj.kset to the subsystem's embedded kset.
received a struct driver_dir_entry, when they performed a
container_of() transform on to receive the specific object type for
which the call was meant.
These callbacks have been converted to accept a struct kobject instead
of struct driver_dir_entry. Since all kobjects belong to a subsystem
that contains kobjects all of the same type, the sysfs operations
have been moved to reside in the subsystem, since they are common for
all kobjects.
4.4 sysfs
Default Attributes subsystems are represented in sysfs via their embedded kobjects. They
follow the same rules as previously mentioned with no exceptions. They
typically receive a top-level directory in sysfs, except when their
embedded kobject is part of another kset, or the parent of the
embedded kobject is explicitly set.
Most subsystems have a set of default attributes associated with an Note that the subsystem's embedded kset must be 'attached' to the
object that registers with them. A subsystem definition may contain a subsystem itself in order to use its rwsem. This is done after
NULL-terminated array of attributes that will be exported when an kset_add() has been called. (Not before, because kset_add() uses its
object is registered with the subsystem. subsystem for a default parent if it doesn't already have one).
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment