====================================================================
Everything you never wanted to know about kobjects, ksets, and ktypes
关于kobject,kset和ktypes的一切,你永远不会想知道
====================================================================
:Author: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
:Last updated: December 19, 2007
Based on an original article by Jon Corbet for lwn.net written October 1, 2003 and located at http://lwn.net/Articles/51437/
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.
理解那些建立在kobject抽象之上的驱动模型困难之一就是没有一个明确的入口。使用kobject需要了解几种不同的类型,而这些类型又相互引用。为了让这一切变得简单,我们将采取多角度方法,以模糊的术语开始,然后逐渐添加细节。为此,现在先给出一些今后会使用到的的一些术语的简单定义。
- 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.
- kobject是一个struct kobject类型的对象。Kobject包含一个名字和一个引用计数。同时一个kobject还包含一个父指针(允许对象被安排成层次结构),一个特定的类型,通常情况下还有一个在sysfs虚拟文件系统里的表现。
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.
通常我们并不关注kobject本身,而应该关注哪些嵌入了kobject的宿主结构体。
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.
任何结构体都不允许包含一个以上的kobject。如果这么做了,引用计数将会出错,你的代码也将会出bug。所以,千万不要这样子做。
- 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.
- ktype是嵌入了kobject的对象的类型。每个嵌入了kobject的对象都需要一个相应的ktype。ktype用来控制当kobject创建和销毁时所发生的操作。
- 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.
- kset是kobject的一组集合。这些kobject可以是同样的ktype,也可以是分别属于不同的ktype。kset是kobject集合的基本容器类型。kset也包含它们自己的kobject,但是你可以放心忽略这些kobject,因为kset的核心代码会自动处理这些kobject。
When you see a sysfs directory full of other directories, generally each of those directories corresponds to a kobject in the same kset.
当你看到一个sysfs目录里面全部是其它目录时,通常每一个目录都对应着一个在同一个kset里的kobject。
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.
我们来看看如何创建和操作这些类型。因为采用自下而上的方法,所以我们需要先回到kobject。
Embedding kobjects
内嵌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.
就内核代码而言,基本上不会创建一个单独的kobject,但也有例外,这到以后再说。其实,kobject通常被用来控制一个更大的特定域对象。因此,你将发现kobject被嵌入到其它的结构体中。如果从面向对象的观点出发,那么kobject可以被看做是被其它类继承的、底层的、抽象的类。kobject实现了一组对于它们本身并不是很有用,但对哪些包含了kobject的对象很有用的功能。另外,C语言不支持直接使用继承,所以必须依靠其它的技术来实现,比如结构嵌套。
(As an aside, for those familiar with the kernel linked list implementation, this is analogous as to how "list_head" structs are rarely useful on their own, but are invariably found embedded in the larger objects of interest.)
(顺便说一句,对于哪些熟悉内核链表实现的开发者来说,这和“list_head”结构体很类似。它们本身并没有什么用,其真正的价值只有在被嵌套进一个更大的结构体中才得以体现。)
So, for example, the UIO code in drivers/uio/uio.c has a structure that defines the memory region associated with a uio device::
举一个例子,drivers/uio/uio.c文件里UIO代码包含了一个定义了内存区域的uio设备::
struct uio_map {
struct kobject kobj;
struct uio_mem *mem;
};
If you have a struct uio_map 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>::
如果你有一个struct uio_map结构体,使用它的成员kobj就能找到嵌套的kobject。但是操作kobject的代码往往会引出一个相反的问题:如果给定一个struct kobject指针,那么包含这个指针的结构体首地址又是什么呢?别投机取巧(比如假设这个kobject是该结构体的第一个字段),那么你应该使用container_of()宏函数,定义在<linux/kernel.h>::
container_of(pointer, type, member)
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.
* "pointer" 是被嵌入的kobject结构体指针,
* "type" 包含kobject结构体对象,
* "member" 该结构体中指向kobject指针的名称。
The return value from container_of() is a pointer to the corresponding container type. So, for example, a pointer "kp" to a struct kobject embedded *within* a struct uio_map could be converted to a pointer to the*containing* uio_map structure with::
container_of()的返回值就是一个相应结构体的指针。例如,一个指向嵌套在uio_map里的struct kobject的指针”kp”,可以这样获得包含它的结构体的指针::
struct uio_map *u_map = container_of(kp, struct uio_map, kobj);
For convenience, programmers often define a simple macro for "back-casting" kobject pointers to the containing type. Exactly this happens in the earlier drivers/uio/uio.c, as you can see here::
为方便起见,程序员通常会定义一个简单的宏,用于“反指”包含这个kobject的容器类型指针。正因为这样,在之前的文件drivers/uio/uio.c中你可以看到::
struct uio_map {
struct kobject kobj;
struct uio_mem *mem
}; #define to_map(map) container_of(map, struct uio_map, kobj)
where the macro argument "map" is a pointer to the struct kobject in question. That macro is subsequently invoked with::
宏参数”map”是一个指向struct kobject的指针。这个宏函数将随后被调用::
struct uio_map *map = to_map(kobj);
Initialization of kobjects
Kobject的初始化
==========================
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()::
创建一个kobject的代码,首先必须初始化这个对象。调用kobject_init()来设置一些内部字段(强制性)::
void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
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::
因为每个kobject都有一个关联的kobj_type,所以正确创建一个kobject时ktype是必须的。调用kobject_init()之后,必须调用kobject_add()在sysfs上注册kobject::
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
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.
这将为kobject设置parent和name。如果这个kobject将关联于一个指定的kset,那么kobj->kset必须在kobject_add()之前被分配好。如果一个kset关联于一个kobject,那么在调用kobject_add()时parent可以是NULL,这时kobject的parent将会是这个kset本身。
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()::
当一个kobject的name已经被设置并添加经kernel之后,就不允许直接操作这个kobject的name了。如果你必须修改name,请使用kobject_rename()::
int kobject_rename(struct kobject *kobj, const char *new_name);
kobject_rename does not perform any locking or have a solid notion of what names are valid so the caller must provide their own sanity checking and serialization.
kobject_rename()不会执行任何锁定操作,也不会验证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.
这里有一个函数kobject_set_name(),但这个函数是遗留问题,而且在将来会被删除。如果你的代码需要调用这个函数,那么这是不正确的,并且必须被修正。
To properly access the name of the kobject, use the function kobject_name()::
要正确访问kobject的name,可以使用函数kobject_name()::
const char *kobject_name(const struct kobject * kobj);
There is a helper function to both initialize and add the kobject to the kernel at the same time, called surprisingly enough kobject_init_and_add()::
这里有一个辅助函数将同时初始化kobject并将其添加至kernel,kobject_init_and_add()::
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.
其中的参数与kobject_init()和kobject_add()里描述的一致。
Uevents
事件
=======
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()::
在一个kobject被注册之后,你需要通过kobject_uevent()向全局宣布它被创建了::
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.
当kobject首次被添加进kernel时,使用KOBJ_ADD action。这个调用必须在所有的attribute或children都被正确初始化之后,因为当这个调用发生时,用户空间将会立即开始寻找它们。
When the kobject is removed from the kernel (details on how to do that are 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.
当kobject从kernel中移除时,KOBJ_REMOVE的uevent将会被kobject core自动创建,所以调用者不必担心手动完成这些。
Reference counts
引用计数
================
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::
一个kobject的主要功能之一就是在它被嵌入的对象中作为一个引用计数器。只要存在该对象的引用,对象(和支持它的代码)就必须继续存在。操作一个kobject的引用计数的底层函数是::
struct kobject *kobject_get(struct kobject *kobj);
void kobject_put(struct kobject *kobj);
A successful call to kobject_get() will increment the kobject's reference counter and return the pointer to the kobject.
对kobject_get()的成功调用,将递增kobject的引用计数,并且返回指向该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.
当一个引用被释放时,调用kobject_put()将递减引用计数,并且可能的话,释放对象。请注意,kobject_init()将引用计数设置为1,所以在建立kobject的代码里需要执行kobject_put()用于最终释放引用。
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.
因为kobject是动态的,所以它不能被声明为静态或者在栈区分配空间,它们应该始终被动态分配。未来的kernel版本将会包含一个对kobject是否静态创建的运行时检查,并且会警告开发人员这种不正确的使用。
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.
如果你使用kobject的理由仅仅是使用引用计数的话,那么请使用struct kref替代kobject。更多关于struct kref的信息请参考Linux内核文档Documentation/kref.txt。
Creating "simple" kobjects
创建“简单”的kobjects
==========================
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::
有时候开发人员希望有一种创建一个在sysfs层次中简单目录的方式,而并不想搞乱本来就错综复杂的ksets,show和store函数,或一些其它的细节。这是单独创建kobjects的例外。要创建这样的kobject,使用这个函数::
struct kobject *kobject_create_and_add(char *name, struct kobject *parent);
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::
该函数将创建一个kobject,并将其放置在指定的父kobject的sysfs中下层的位置。要简单地创建与这个kobject关联的属性,使用函数::
int sysfs_create_file(struct kobject *kobj, struct attribute *attr);
or::
int sysfs_create_group(struct kobject *kobj, struct attribute_group *grp);
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.
这两种使用kobject_create_and_add()创建的kobject的属性类型都可以是kobj_attribute,所以没有创建自定义属性的需要。
See the example module, samples/kobject/kobject-example.c for an implementation of a simple kobject and attributes.
查看示例模块samples/kobject/kobject-example.c,一个简单的kobject和属性的实现。
ktypes and release methods
ktypes和release方法
==========================
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.
到目前为止我们遗漏了一个重要的事情,那就是当一个kobject的引用计数达到0时,将会发生什么事情。通常,创建kobject的代码并不知道这种情况何时发生。如果它们知道何时发生,那么把kobject放在结构体的首位可能会有那么一点点帮助。即使是一个可预测的对象生命周期也将变得复杂,特别是在当sysfs作为kernel的一部分被引入时,它可以获取到任意在系统中注册的kobject的引用。
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.
结论就是,一个被kobject保护的结构体不能在这个kobject引用计数到0之前被释放。而这个引用计数又不被创建这个kobject的代码所直接控制,所以必须在这个kobject的最后一个引用消失时异步通知这些代码。
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.
一旦你通过kobject_add()注册你的kobject之后,永远不要直接使用kfree()释放它。唯一安全的途径是使用kobject_put()。总是在kobject_init()之后使用kobject_put()是避免bug的很好做法。
This notification is done through a kobject's release() method. Usually such a method has a form like::
这个通知是通过kobject的release()函数完成的。该函数通常具有这样的形式::
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. 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.
很重要的一点,怎么强调也不过分:每个kobject必须有一个release()函数,而且这个函数被调用之前kobject必须继续存在(保持一致的状态)。如果不符合这些限制,那么代码是有bug的。需要注意的是,如果你忘记提供一个release()函数,kernel会警告你。不要试图提供一个”NULL”的release()函数来摆脱这个警告,如果你这样做,会受到kobject维护者们无情的嘲笑。
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.
注意,尽管在release()函数中kobject的name是可用的,但是千万不要在这个回调函数中修改它。否则将会在kobject core中发生令人不愉快的内存泄漏问题。
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::
有趣的是release()函数并没有保存到kobject之中,而是关联在它的ktype成员中。让我们来介绍struct kobj_type::
struct kobj_type
{
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};
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().
这个结构体式用来描述一个特定类型的kobject(或者更确切地说,包含kobject的对象)。每个kobject都需要一个关联的kobj_type结构体,当你调用kobject_init()或kobject_init_and_add()时必须指定一个指向kobj_type结构体的指针。
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.
当然struct kobj_type中的release字段就是一个指向同类型对象release()方法的函数指针。另外两个字段(sysfs_ops和default_attrs)是用来控制这些类型的对象在sysfs里是如何表现的,这已经超出了本文的讨论范围。
The default_attrs pointer is a list of default attributes that will be automatically created for any kobject that is registered with this ktype.
default_attrs成员指针是一个在任何属于这个ktype的kobject注册时自动创建的默认属性列表。
ksets
kset结构体
=====
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.
Kset仅仅是一个需要相互关联的kobject集合。在这里没有任何规定它们必须是同样的ktype,但如果它们不是一样的ktype,则一定要小心处理。
A kset serves these functions:
一个kset提供以下功能:
- 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."
- 它就像一个装有一堆对象的袋子。Kernel可以用一个kset来跟踪像“所有的块设备”或者“所有的PCI设备”这样的东西。
- 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.
- 一个kset也是一个sysfs里的子目录,该目录能够看见这些相关的kobject。每个kset都另外包含一个kobject,这个kobject可以用来设置成其它的kobjects的parent。sysfs层次结构中的顶层目录就是通过这样的方法构建的。
- Ksets can support the "hotplugging" of kobjects and influence how uevent events are reported to user space.
- ksets还可以支持kobject的“热插拔”,并会影响uevent事件如何报告给用户空间。
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.
以面向对象的观点来看,”kset”是一个顶层容器类。Kset包含有它们自己的kobject,这个kobject是在kset代码管理之下的,而且不允许其它用户进行操作。
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 kset have that kset (or, strictly, its embedded kobject) in their parent.
一个kset使用标准的kernel链表来保存它的children。Kobjects通过它们的kset字段回指向包含它们的kset。在几乎所有的情况下,属于某kset的kobject的paren都指向这个kset(严格地说是嵌套进这个kset的kobject)。
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::
正因为一个kset包含了一个kobject,所以始终应该动态创建这个kset,千万不要将其声明为静态或在栈区分配空间。创建一个kset的方法::
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::
当你使用完一个kset时,调用下面这个函数::
void kset_unregister(struct kset *kset);
to destroy it. This removes the kset from sysfs and decrements its reference count. When the reference count goes to zero, the kset will be released. Because other references to the kset may still exist, the release may happen after kset_unregister() returns.
去销毁它。这将从sysfs中删除kset并减少其引用计数。当引用计数为0时,kset将会被释放。由于对kset的其它引用仍然可能存在,因此释放可能在kset_unregister()返回后发生。
An example of using a kset can be seen in the samples/kobject/kset-example.c file in the kernel tree.
内核树中的samples/kobject/kset-example.c文件是一个关于如何使用kset的示例。
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::
如果一个kset希望控制那些与它相关联的kobject的uevent操作,可以使用struct kset_uevent_ops来进行处理::
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);
};
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.
Filter函数允许kset阻止一个特定的kobject的uevent是否发送到用户空间。如果这个函数返回0,则uevent将不会被发出。
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.
name函数用来重写哪些被uevent发送到用户空间的kset的默认名称。默认情况下,这个名称应该和kset本身的名称相同,但这个函数的出现将可以改写这个名称。
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.
uevent函数会向即将被发送到用户空间的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.
有人可能会问,当一个kobject加入到kset时并没有提供完成这些功能的函数。答案就是这些任务由kobject_add()来完成,kobject的成员kset必须指向它将被加入到的kset,然后kobject_add()会帮你把剩下的工作干完。
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.
如果一个属于某个kset的kobject没有设置它的parent kobject,那么它将被添加到kset的目录中去。但并不是kset的所有成员都一定存在于kset目录下。如果在kobject被添加前就指明了它的parent kobject,那么该kobject将被注册到这个kset下,然后添加到它的parent kobject下。
Kobject removal
Kobject的移除
===============
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.
当kobject core成功的注册了一个kobject之后,这个kobject必须在代码中实现完成使用后的销毁。要做到这一点,请调用kobject_put()。通过这个调用,kobject core会自动清理所有通过这个kobject分配的内存空间。如果曾经为了这个kobject发送过一个KOBJ_ADD uevent,那么一个相应的KOBJ_REMOVE uevent将会被发送,并且任何一个其它的sysfs维护者都将为这个调用做出相应的处理。
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.
如果你需要分两步来删除一个kobject的话(也就是说在你需要销毁一个对象时不允许sleep),那么请使用kobject_del()来从sysfs中注销这个kobject。这将使得kobject“不可见”,但是它并没有被清理,并且它的引用计数也没变。在随后调用kobject_put()去完成这个kobject相关的内存空间的清理。
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.
如果建立了一个循环引用的话,kobject_del()可以用来删除指向parent对象的引用。当某个parent对象又引用了它的child时,这是非常有用的。循环引用必须显示地通过调用kobject_del()来打破,这样做之后,将会调用一个release函数,并且这些先前在循环引用中的对象才会彼此释放。
Example code to copy from
示例代码
=========================
For a more complete example of using ksets and kobjects properly, see the example programs samples/kobject/{kobject-example.c,kset-example.c}, which will be built as loadable modules if you select CONFIG_SAMPLE_KOBJECT.
想要获得更完整的关于正确使用kset和kobject的例子,请参考示例程序samples/kobject/{kobject-example.c,kset-example.c}。可以通过选择编译条件CONFIG_SAMPLE_KOBJECT来把这些示例编译成可装载模块。