Linux Device Drivers (3rd Edition) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Linux Device Drivers (3rd Edition) [Electronic resources] - نسخه متنی

Jonathan Corbet, Greg Kroah-Hartman, Alessandro Rubini

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








14.1. Kobjects, Ksets, and Subsystems


The kobject is the




fundamental
structure
that holds the device
model together. It was initially conceived as a simple reference
counter, but its responsibilities have grown over time, and so have
its fields. The tasks handled by struct
kobject and its supporting code now include:

Reference counting of objects


Often, when a kernel object is created, there is no way to know just
how long it will exist. One way of tracking the lifecycle of such
objects is through reference counting. When no code in the kernel
holds a reference to a given object, that object has finished its
useful life and can be deleted.


Sysfs representation


Every object that shows up in sysfs has, underneath it, a kobject
that interacts with the kernel to create its visible representation.


Data structure glue


The device model is, in its entirety, a fiendishly complicated data
structure made up of multiple hierarchies with numerous links between
them. The kobject implements this structure and holds it together.


Hotplug event handling


The kobject subsystem handles the generation of events that notify
user space about the comings and goings of hardware on the system.



One might conclude from the preceding list that the kobject is a
complicated structure. One would be right. By looking at one piece at
a time, however, it is possible to understand this structure and how
it works.


14.1.1. Kobject Basics


A kobject has the type struct kobject; it is
defined in <linux/kobject.h>. That file
also includes declarations for a number of other structures related
to kobjects and, of course, a long list of functions for manipulating
them.


14.1.1.1 Embedding kobjects

Before we get into

the
details, it is worth taking a moment to understand how kobjects are
used. If you look back at the list of functions handled by kobjects,
you see that they are all services performed on behalf of other
objects. A kobject, in other words, is of little interest on its own;
it exists only to tie a higher-level object into the device model.

Thus, it is rare (even unknown) for kernel code to create a
standalone kobject; instead, kobjects are used to control access to a
larger, domain-specific object. To this end, kobjects are 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 that are not particularly useful by
themselves but that are nice to have in other objects. The C language
does not allow for the direct expression of inheritance, so other
techniquessuch as embedding one structure in
anothermust be used.

As an example, let's look back at
struct cdev, which we
encountered in Chapter 3. That
structure, as found in the 2.6.10 kernel, looks like this:

struct cdev {
struct kobject kobj;
struct module *owner;
struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};

As we can see, the cdev structure has a kobject
embedded within it. If you have one of these structures, finding its
embedded kobject is just a matter of using the
kobj field. Code that works with kobjects often
has the opposite problem, however: given a struct
kobject
pointer, what is the pointer to the containing
structure? You should avoid tricks (such as assuming that the kobject
is at the beginning of the structure), and, instead, use the
container_of macro (introduced in
Section 3.5.1.
So the way to convert a
pointer
to
a struct kobject called
kp embedded within a struct
cdev
would be:

struct cdev *device = container_of(kp, struct cdev, kobj);

Programmers often define a simple macro for
"back-casting" kobject
pointers to the containing type.


14.1.1.2 Kobject initialization

This book has presented a
number
of types with simple mechanisms for initialization at compile or
runtime. The initialization of a kobject is a bit more complicated,
especially when all of its functions are used. Regardless of how a
kobject is used, however, a few steps must be performed.

The first of those is to simply set the entire kobject to
0, usually with a call to
memset. Often this initialization happens as
part of the zeroing of the structure into which the kobject is
embedded. Failure to zero out a kobject often leads to very strange
crashes further down the line; it is not a step you want to skip.

The next step is to set up some of the internal fields with a call to
kobject_init( ):

void kobject_init(struct kobject *kobj);

Among other things, kobject_init sets the
kobject's reference count to one. Calling
kobject_init is not sufficient, however. Kobject
users must, at a minimum, set the name of the kobject; this is the
name that is used in sysfs entries. If you dig through the kernel
source, you can find the code that copies a string directly into the
kobject's name field, but that
approach should be avoided. Instead, use:

int kobject_set_name(struct kobject *kobj, const char *format, ...);

This function takes a printk-style variable
argument list. Believe it or not, it is actually possible for this
operation to fail (it may try to allocate memory); conscientious code
should check the return value and react accordingly.

The other kobject fields that should be set, directly or indirectly,
by the creator are ktype, kset,
and parent. We will get to these later in this
chapter.


14.1.1.3 Reference count manipulation

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 that
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);

A successful call to kobject_get increments the
kobject's reference counter and returns a pointer to
the kobject. If, however, the kobject is already in the process of
being destroyed, the operation fails, and
kobject_get returns NULL.
This return value must always be tested, or no end of unpleasant race
conditions could result.

When a reference is released, the call to
kobject_put decrements the reference count and,
possibly, frees the object. Remember that
kobject_init sets the reference count to one; so
when you create a kobject, you should make sure that the
corresponding kobject_put call is made when that
initial reference is no longer needed.

Note that, in many cases, the reference count in the kobject itself
may not be sufficient to prevent race conditions. The existence of a
kobject (and its containing structure) may well, for example, require
the continued existence of the module that created that kobject. It
would not do to unload that module while the kobject is still being
passed around. That is why the cdev structure we
saw above contains a struct
module pointer. Reference counting for
struct cdev is implemented as follows:

struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (owner && !try_module_get(owner))
return NULL;
kobj = kobject_get(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}

Creating a reference to a cdev structure requires
creating a reference also to the module that owns it. So
cdev_get uses
try_module_get to attempt to increment that
module's usage count. If that operation succeeds,
kobject_get is used to increment the
kobject's reference count as well. That operation
could fail, of course, so the code checks the return value from
kobject_get and releases its reference to the
module if things don't work out.


14.1.1.4 Release functions and kobject types

One important thing

still missing from the discussion is
what happens to a kobject when its reference count reaches
0. The code that created the kobject generally
does not know when that will happen; if it did, there would be little
point in using a reference count in the first place. Even predictable
object life cycles become more complicated when sysfs is brought in;
user-space programs can keep a reference to a kobject (by keeping one
of its associated sysfs files open) for an arbitrary period of time.

The end result is that a structure protected by a kobject cannot be
freed at any single, predictable point in the
driver's lifecycle, but in code that must be
prepared to run at whatever moment the kobject's
reference count goes to 0. The reference count is
not under the direct control of the code that created the kobject. So
that code must be notified asynchronously whenever the last reference
to one of its kobjects goes away.

This notification is done through a kobject's
release

method. Usually, this method has a form such as:

void my_object_release(struct kobject *kobj)
{
struct my_object *mine = container_of(kobj, struct my_object, kobj);
/* Perform any additional cleanup on this object, then... */
kfree(mine);
}

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. It risks freeing the object when it
is still in use, or it fails to release the object after the last
reference is returned.

Interestingly, the release method is not stored
in the kobject itself; instead, it is associated with the type of the
structure that contains the kobject. This type is tracked with a
structure of type struct kobj_type, often simply
called a "ktype." This structure
looks like the following:

struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};

The release field in struct
kobj_type
is, of course, a pointer to the
release method for this type of kobject. We will
come back to the other two fields (sysfs_ops and
default_attrs) later in this chapter.

Every kobject needs to have an associated
kobj_type structure. Confusingly, the pointer to
this structure can be found in two different places. The kobject
structure itself contains a field (called ktype)
that can contain this pointer. If, however, this kobject is a member
of a kset, the kobj_type pointer is provided by
that kset instead. (We will look at ksets in the next section.)
Meanwhile, the macro:

struct kobj_type *get_ktype(struct kobject *kobj);

finds the kobj_type pointer for a given kobject.


14.1.2. Kobject Hierarchies, Ksets, and Subsystems


The kobject structure is
often

used to link
together objects into a hierarchical structure that matches the
structure of the subsystem being modeled. There are two separate
mechanisms for this linking: the parent pointer
and ksets.

The parent field in struct
kobject
is a pointer to another kobjectthe one
representing the next level up in the hierarchy. If, for example, a
kobject represents a USB device, its parent
pointer may indicate the object representing the hub into which the
device is plugged.

The main use for the parent pointer is to position
the object in the sysfs hierarchy. We'll see how
this works in Section 14.2.


14.1.2.1 Ksets

In many ways, a kset looks like an extension of the
kobj_type structure; a kset is a collection of
kobjects embedded within structures of the same type. However, while
struct kobj_type concerns
itself with the type of an object, struct
kset is concerned with aggregation and collection.
The two concepts have been separated so that objects of identical
type can appear in distinct sets.

Therefore, the main function of a kset is containment; it can be
thought of as the top-level container class for kobjects. In fact,
each kset contains its own kobject internally, and it can, in many
ways, be treated the same way as a kobject. It is worth noting that
ksets are always represented in sysfs; once a kset has been set up
and added to the system, there will be a sysfs directory for it.
Kobjects do not necessarily show up in sysfs, but every kobject that
is a member of a kset is represented there.

Adding a kobject to a kset is usually done when the object is
created; it is a two-step process. The kobject's
kset field must be pointed at the kset of
interest; then the kobject should be passed to:

int kobject_add(struct kobject *kobj);

As always, programmers should be aware that this function can fail
(in which case it returns a negative error code) and respond
accordingly. There is a convenience function provided by the kernel:

extern int kobject_register(struct kobject *kobj);

This function is simply a combination of
kobject_init and
kobject_add.

When a kobject is passed to kobject_add, its
reference count is incremented. Containment within the kset is, after
all, a reference to the object. At some point, the kobject will
probably have to be removed from the kset to clear that reference;
that is done with:

void kobject_del(struct kobject *kobj);

There is also a kobject_unregister function,
which is a combination of kobject_del and
kobject_put.

A kset keeps its children in a standard kernel linked list. In almost
all cases, the contained kobjects also have pointers to the kset (or,
strictly, its embedded kobject) in their parent's
fields. So, typically, a kset and its kobjects look something like
what you see in Figure 14-1.
Bear in mind that:

  • All of the contained kobjects in the diagram are actually embedded
    within some other type, possibly even other ksets.

  • It is not required that a kobject's parent be the
    containing kset (although any other organization would be strange and
    rare).



Figure 14-2. A simple kset hierarchy


14.1.2.2 Operations on ksets

For initialization and setup, ksets have an

interface very similar
to
that of kobjects. The following functions exist:

void kset_init(struct kset *kset);
int kset_add(struct kset *kset);
int kset_register(struct kset *kset);
void kset_unregister(struct kset *kset);

For the most part, these
functions
just call the analogous kobject_ function on the
kset's embedded kobject.

To manage the reference counts of ksets, the situation is about the
same:

struct kset *kset_get(struct kset *kset);
void kset_put(struct kset *kset);

A kset also has a name, which is stored in the embedded kobject. So,
if you have a kset called my_set, you would set
its name with:

kobject_set_name(&my_set->kobj, "The name");

Ksets also have a pointer (in the ktype field) to
the kobj_type structure describing the kobjects it
contains. This type is used in preference to the
ktype field in a kobject itself. As a result, in
typical usage, the ktype field in
struct kobject is left
NULL, because the same field within the kset is
the one actually used.

Finally, a kset contains a subsystem pointer (called subsys). So
it's time to talk about subsystems.


14.1.2.3 Subsystems

A subsystem is
a

representation for a high-level portion of the kernel as a whole.
Subsystems usually (but not always) show up at the top of the sysfs
hierarchy. Some example subsystems in the kernel include
block_subsys (/sys/block, for
block devices), devices_subsys
(/sys/devices, the core device hierarchy), and a
specific subsystem for every bus type known to the kernel. A driver
author almost never needs to create a new subsystem; if you feel
tempted to do so, think again. What you probably want, in the end, is
to add a new class, as discussed in Section 14.5.

A subsystem is represented by a simple structure:

struct subsystem {
struct kset kset;
struct rw_semaphore rwsem;
};

A subsystem, thus, is really just a wrapper around a kset, with a
semaphore thrown in.

Every kset must belong to a subsystem. The subsystem membership helps
establish the kset's position in the hierarchy, but,
more importantly, the subsystem's
rwsem semaphore is used to serialize access to a
kset's internal-linked list. This membership is
represented by the subsys pointer in
struct kset. Thus, one can find each
kset's containing subsystem from the
kset's structure, but one cannot find the multiple
ksets contained in a subsystem directly from the subsystem structure.

Subsystems are often declared with a special macro:

decl_subsys(name, struct kobj_type *type, 
struct kset_hotplug_ops *hotplug_ops);

This macro creates a struct subsystem with a name
formed by taking the name given to the macro and
appending _subsys to it. The macro also
initializes the internal kset with the given type
and hotplug_ops. (We discuss hotplug operations
later in this chapter.)

Subsystems have the usual list of setup and teardown functions:

void subsystem_init(struct subsystem *subsys);
int subsystem_register(struct subsystem *subsys);
void subsystem_unregister(struct subsystem *subsys);
struct subsystem *subsys_get(struct subsystem *subsys)
void subsys_put(struct subsystem *subsys);

Most of these operations just act upon the subsystem's
kset.


    / 202