Linux Device Models (Kobject, Kset, and Subsystem) (ii)

Source: Internet
Author: User
Tags sprintf strcmp

Description of the problem: in the previous article we know that/sys is the implementation information that includes the kernel and the driver, and the user is able to/sys this interface. This interface allows the user to list the full picture of the kernel device. This article will look at how this device model is built from the perspective of the Linux kernel.

1. Kobject Structure

in the Linux kernel, Kobject is the basis for composing the Linux device model, A folder in a kobject corresponding SYSFS .

From an object-oriented perspective. Kobject can be thought of as the base class for all device objects, because C does not have object-oriented syntax, so it is common to embed kobject into other structures to achieve similar effects, where other structures can be considered as kobject derived classes. Kobject provides a number of useful features for the Linux device model, such as reference counting. Interface abstraction, parent-child relationships, and so on.

The reference count is essentially implemented using KREF.

in addition. Another important data structure for the Linux device model is kset. Kset itself is also a kobject, so it behaves as a folder in Sysfs , but it differs from kobject in that Kset can be viewed as a container, assuming you are comparing it to C + + Container classes like List are not allowed. Kset can be used as a container, the interior of which is embedded in a doubly linked list structure struct list_head.

Descriptive narrative of kobject in the kernel

struct Kobject {    const char      *name;    struct List_head    entry;    struct Kobject      *parent;    struct Kset     *kset;    struct Kobj_type    *ktype;    struct sysfs_dirent *sd;    struct Kref     kref;    unsigned int state_initialized:1;    unsigned int state_in_sysfs:1;    unsigned int state_add_uevent_sent:1;    unsigned int state_remove_uevent_sent:1;    unsigned int uevent_suppress:1;};

The devices in the kernel are organized in a tree form, in which the upper nodes can be regarded as the parent nodes of the lower nodes, reflecting the relationship between the parent folder and the subordinate folder in the Sysfs. in the kernel, it is kobject that helps us to achieve such a parent-child relationship.。 In the definition of Kobject, name represents the name of Kobject in SYSFS; the pointer parent is used to point to Kobject's father; kref people should be more familiar with it. The kobject uses it to implement the reference count, and the Kset pointer is used to point to the Kset the kobject belongs to, and the following is a detailed description of how Kset is used. For Ktype, suppose it's just words too literally. Should be used to describe the type of narrative kobject information.

The definition of Ktype is as follows:

struct Kobj_type {    void (*release) (struct kobject *kobj);    const struct Sysfs_ops *sysfs_ops;    struct attribute **default_attrs;};
The function pointer release is used for Kref. when the reference count is 0, the function that the pointer points to will be called to free memory. What do Sysfs_ops and attribute do with it? Mentioned in the previous article. A folder in the corresponding Sysfs of a kobject. The files under the folder are implemented by Sysfs_ops and attribute, among them. Attribute defines the properties of the Kobject, and in Sysfs a corresponding file, Sysfs_ops is used to define how to read and write the file. The attribute in Ktype is the default attribute, and in addition to the use of more flexible means, the focus of this article is still placed in the default attribute.
#include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/ Kobject.h>struct My_kobj {//embedded kobject structure int val;struct kobject kobj;}; struct My_kobj *obj1, *obj2;struct kobj_type my_type;struct attribute name_attr = {. Name = "Name",//file name. Mode = 0444,// Specify access permissions for a file};struct attribute val_attr = {. Name = "Val",//file name. Mode = 0666,//Specify the file's access rights};struct attribute *my_attrs[] = {&A Mp;name_attr, the name variable in the &val_attr,null,};/* struct attribute is used to specify the file name. The mode variable is used to specify access permissions for the file. It is important to emphasize that the last item of the array my_attrs must be assigned null, otherwise it will cause the kernel to oops.

*/ssize_t my_show (struct kobject *kobj, struct attribute *attr, char *buffer) {struct My_kobj *obj = container_of (kobj, str UCT my_kobj, kobj); ssize_t count = 0;if (strcmp (attr->name, "name") = = 0) {count = sprintf (buffer, "%s\n", Kobject_name (Kobj));} else if (strcmp (Attr->name, "val") = = 0) {count = sprintf (buffer, "%d\n", Obj->val);} return count;} ssize_t my_store (struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size) {struct My_kobj *obj = cont Ainer_of (kobj, struct my_kobj, kobj); if (strcmp (Attr->name, "val") = = 0) {sscanf (buffer, "%d", &obj->val);} return size;} struct Sysfs_ops my_sysfsops = {. Show = My_show,.store = My_store,};void obj_release (struct kobject *kobj) {struct my_kobj *obj = container_of (kobj, struct my_kobj, kobj);p rintk (kern_info "Obj_release%s\n", Kobject_name (&obj->kobj)); Kfree (obj);} static int __init mykobj_init (void) {PRINTK (kern_info "mykobj_init\n"); obj1 = kzalloc (sizeof (struct my_kobj), Gfp_ KERNEL); Assign Obj1 and Obj2 and assignValue if (!obj1) {return-enomem;} Obj1->val = 1;obj2 = kzalloc (sizeof (struct my_kobj), Gfp_kernel), if (!obj2) {kfree (obj1); return-enomem;} Obj2->val = 2;my_type.release = Obj_release;my_type.default_attrs = My_attrs;my_type.sysfs_ops = &my_sysfsops; Kobject_init_and_add (&obj1->kobj, &my_type, NULL, "mykobj1"); /* function to initialize the Kobject and add it to the architecture of the device model */kobject_init_and_add (&obj2->kobj, &my_type, &obj1->kobj, " Mykobj2 ")/*kobject_init is used to initialize the Kobject structure, Kobject_add is used to add kobj to the device model. In the implementation, we first initialize and increment the obj1, the call in the argument, the parent is assigned to NULL, indicating that obj1 no parent object, reflected in Sysfs, My_kobj1 folder will appear under the/sys now. Obj2 's parent object is set to Obj1, the My_kobj2 folder will appear below the/sys/my_kobj1 now. mentioned earlier. Kobject also provides reference counting functionality, although it is essentially leveraging kref, but also provides additional interfaces for user use.

Kobject_init_and_add and Kobject_init These two functions are called after. The reference count for Kobj is initialized to 1, so remember to use Kobject_put to release the reference count when Module_exit. */return 0;} static void __exit mykobj_exit (void) {PRINTK (kern_info "mykobj_exit\n"); Kobject_del (&obj2->kobj);/* First child object. Stepfather Object */kobject_put (&obj2->kobj); Kobject_del (&obj1->kobj); Kobject_put (&obj1->kobj); return;} The role of/*kobject_del is to remove kobject from the plant model tree. At the same time, the corresponding folder in the SYSFS will also be deleted. What needs to be pointed out here is. The order of release should be the first child object, the stepfather object.

Because Kobject_init_and_add and Kobject_add both functions call Kobject_get to increase the reference count of the parent object, Kobject_del needs to call Kobject_put to reduce the reference count of the parent object. In this example, assuming that Obj1 is released through Kobject_put first, the Kobject_del (&obj2->kobj) will have a memory error. */module_init (Mykobj_init); Module_exit (Mykobj_exit); Module_license ("GPL");


1.1 Kobject Self-summary

Kobject is the basis for composing a Linux device model, A folder in the corresponding Sysfs of a kobject. in fact, the meaning of its existence is to connect high-level objects to the device model. so the kobject is embedded in other structures. Kobject can be seen as a top-level base class, and other classes are derived from it. Kobject implements a series of methods that have no special effect on themselves and are effective for other objects.

initially it is only counted as a simple reference, but over time, its tasks are increasing. The tasks and support code currently handled by Kobject include: object reference count: One way to track an object's life cycle is to use reference counting.

When no kernel code holds a reference to the object, the object ends its valid lifetime and can be deleted.


This article code download


2, Kset

in this implementation, we have established two objects obj1 and obj2. Obj1 is the parent object of OBJ2. Assumptions are spread. Obj1 can have many other sub-objects. In the Linux kernel, such an architectural approach is actually not much of a real value. One of the limited uses is to create subfolders in the SYSFS (the Linux kernel has such a way of using this, in this case. Directly invoke the kernel provided by the kobject_create to implement, do not need to define the data structure and embedded kobject), and. There are other ways to create subfolders . We know. The original purpose of the Linux device model was to facilitate power management, which required a traversal from top to bottom, in which the entire sub-object was not accessible through obj1. The biggest implication of this practice is that it gives us a clearer understanding of how kobject is used. Normally, the kobject only needs to be used in the leaf nodes, and the upper nodes use Kset.

struct Kset {    struct list_head list;    spinlock_t List_lock;    struct Kobject kobj;    const struct kset_uevent_ops *uevent_ops;};
the kobj in the Kset structure shows that it is also a kobject,list variable used to organize all of its sub-objects.

<span style= "Font-family:microsoft yahei;font-size:12px;" > #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/ Kobject.h>struct My_kobj {//embedded kobject structure int val;struct kobject kobj;}; struct My_kobj *obj1, *obj2;struct kset *my_kset;struct kobj_type my_type;struct attribute name_attr = {. Name = ' name ',// File name. Mode = 0444,//Specify the file's access rights};struct attribute val_attr = {. Name = "Val",//file name. Mode = 0666,//Specify the file's access rights};struct attrib Ute *my_attrs[] = {&name_attr, the name variable in the &val_attr,null,};/* struct struct attribute is used to specify the file name, and the mode variable is used to specify the access permission for the file. What needs to be highlighted here is. The last item of the array my_attrs must be assigned null, otherwise it will cause the kernel to oops.

*/ssize_t my_show (struct kobject *kobj, struct attribute *attr, char *buffer) {struct My_kobj *obj = container_of (kobj, str UCT my_kobj, kobj); ssize_t count = 0;if (strcmp (attr->name, "name") = = 0) {count = sprintf (buffer, "%s\n", Kobject_name (Kobj));} else if (strcmp (Attr->name, "val") = = 0) {count = sprintf (buffer, "%d\n", Obj->val);} return count;} ssize_t my_store (struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size) {struct My_kobj *obj = cont Ainer_of (kobj, struct my_kobj, kobj); if (strcmp (Attr->name, "val") = = 0) {sscanf (buffer, "%d", &obj->val);} return size;} struct Sysfs_ops my_sysfsops = {. Show = My_show,.store = My_store,};void obj_release (struct kobject *kobj) {struct my_kobj *obj = container_of (kobj, struct my_kobj, kobj);p rintk (kern_info "Obj_release%s\n", Kobject_name (&obj->kobj)); Kfree (obj);} static int __init mykset_init (void) {PRINTK (kern_info "mykset_init\n"); My_kset = Kset_create_and_add ("My_kset", NULL, NULL); if (!my_kset){Return-enomem;} obj1 = kzalloc (sizeof (struct my_kobj), Gfp_kernel), if (!obj1) {kset_unregister (my_kset); return-enomem;} Obj1->val = 1;obj2 = kzalloc (sizeof (struct my_kobj), Gfp_kernel), if (!obj2) {kset_unregister (my_kset); Kfree (OBJ1); Return-enomem;} Obj2->val = 2;obj1->kobj.kset = My_kset;obj2->kobj.kset = My_kset;my_type.release = Obj_release;my_ Type.default_attrs = My_attrs;my_type.sysfs_ops = &my_sysfsops;kobject_init_and_add (&obj1->kobj, &my _type, NULL, "mykobj1");/* function to initialize Kobject and add it to the architecture of the device model */kobject_init_and_add (&obj2->kobj, &my_type, NULL, "Mykobj2");/*kobject_init is used to initialize the Kobject structure, Kobject_add is used to add kobj to the device model. In practice, we first initialize and increment the obj1. In the calling parameter. The parent is assigned null. Indicates that Obj1 has no parent object and is reflected in the SYSFS. My_kobj1 folder will appear under the/sys now, Obj2 's parent object is set to Obj1, then My_kobj2 folder will appear below/sys/my_kobj1 now.

As mentioned earlier, Kobject also provides the function of reference counting, although it is essentially leveraging kref, but it also provides additional interfaces for the user to use. After Kobject_init_and_add and Kobject_init are called, the reference count of Kobj is initialized to 1, so remember to use Kobject_put to release the reference count when Module_exit.

*/return 0;} static void __exit mykset_exit (void) {PRINTK (kern_info "mykset_exit\n"); Kobject_del (&obj1->kobj);/* First child object, stepfather object */kobject_put (&obj1->kobj); Kobject_del (&obj2->kobj); Kobject_put (&obj2->kobj); kset_ Unregister (my_kset); return;} The role of/*kobject_del is to remove the kobject from the plant model, and the corresponding folder will be deleted at the same time Sysfs. It should be noted here that the order of release should be the first child object. The Stepfather object.

Because Kobject_init_and_add and Kobject_add both functions call Kobject_get to increase the reference count of the parent object, Kobject_del needs to call Kobject_put to reduce the reference count of the parent object. In this example, it is assumed that the Obj1 is released by Kobject_put first. The Kobject_del (&obj2->kobj) will have a memory error. */module_init (Mykset_init); Module_exit (Mykset_exit); Module_license ("GPL");</span>


In Module_init, we first call Kset_create_and_add to create the My_kset, then assign My_kset to Obj1 and Obj2, and finally call Kobject_init_and_add to join Obj1 and obj 2. It is important to note that the parent in the Kobject_init_and_add parameter is null, in such a case. The parent object of OBJ1 and Obj2 is determined by the Kset pointer in the KOBJECT structure, which in this practice is my_kset. In the Module_exit. We also need an extra call to Kset_unregister to release the My_kset that we created earlier.

2.1 Kset Self-summary

kset like the expansion of the kobj_type structure; a kset is embedded in the same type of structure. A collection of Kobject. But struct Kobj_type is concerned with the type of object, while struct Kset is concerned with the aggregation and collection of objects. Its main function is containment. Can be thought of as the top-level container class of kobjects. Each kset includes its own kobject, and is capable of handling kset in a variety of kobject ways. Ksets always appear in the SYSFS; Once Kset is set up and added to the system, a folder is created in Sysfs. Kobjects does not have to be represented in Sysfs, but each Kobject member in Kset is expressed in SYSFS.

Add Kobject to Kset, which is usually completed when Kobject is created, and the process is divided into 2 steps:
(1) Complete initialization of kobject. Pay special attention to mane and parent and initialize.


(2) point the Kset member of Kobject to the target kset.
(3) Pass the Kobject to the following function


3. Subsystems

A subsystem is a representation of some high-level parts of the entire kernel. Subsystems are often (but not necessarily) out of the top layer in today's SYSFS hierarchy. The kernel subsystem contains Block_subsys (/sys/block block devices), Devices_subsys (/sys/devices core device layer), and a specific subsystem known to the kernel for various buses.
There is no longer a subsystem data structure for the new kernel. Replaced with a kset.

Each of the kset must belong to a subsystem. subsystem members help the kernel locate Kset in a hierarchical structure.



/* Subsystem pass often uses the following macro declaration: */
Decl_subsys (name, struct kobj_type *type, struct kset_uevent_ops * uevent_ops);
/* Operation function of SUBSYSTEM: */
void Subsystem_init (struct kset *s);
int subsystem_register (struct kset *s);
void Subsystem_unregister (struct kset *s);
struct subsystem *subsys_get (struct kset *s)
void Subsys_put (struct kset *s);

/* These functions are essentially encapsulated by the Kset operation function to implement the operation of the subsystem */




Linux Device Models (Kobject, Kset, and Subsystem) (ii)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.