Kobject embedded structure of Linux device model

Source: Internet
Author: User
Tags sprintf strcmp

Problem Description: Earlier we know that/sys is a kernel and driver implementation information, the user can/sys this interface, the user through this interface can be a list of the core device of the full picture. 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 kobject corresponds to a directory in the Sysfs . From an object-oriented perspective, Kobject can be seen 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, the Linux device model has an important data structure Kset. Kset itself is also a kobject, so it behaves as a directory in Sysfs , but it differs from kobject in that Kset can be seen as a container, if you compare 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.

Description of the 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 directory and the subordinate directory in the SYSFS. in the kernel, it was kobject that helped us achieve this kind of parent-child relationship.. In the definition of Kobject, name refers to the name of Kobject in SYSFS; the pointer parent is used to point to Kobject's parents; kref people should be more familiar with it, kobject to implement reference counting The Kset pointer is used to point to the kset that the kobject belongs to, and the usage of Kset is described in detail below, and for Ktype, if it is only words too literally, it should be used to describe the type information of Kobject. Ktype is defined 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 for KREF use, 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? As mentioned in the previous article, a kobject corresponds to a directory in the SYSFS,The files under the directory are implemented by Sysfs_ops and attribute, where attribute defines the properties of the Kobject, a file in Sysfs, and sysfs_ops to define the way to read and write the file. The attribute in Ktype is the default attribute, and a more flexible approach can be used, the focus of this article is on 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,//refers to File access};struct Attribute val_attr = {. Name = "Val",//file name. Mode = 0666,//Specify the access rights of the file};struct attribute *my_attrs[] = {&amp ; name_attr, the name variable in the &val_attr,null,};/* struct attribute is used to specify the file name, and the mode variable is used to specify the access rights to the files. 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 = container_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 assign the value 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 add to the Obj1 action, the invocation parameter, the parent is assigned to NULL, indicating that obj1 no parent object, reflected in the SYSFS, My_kobj1 directory will appear in/sys, Obj2 's parent object is set to Obj1, then My_ The Kobj2 directory will appear under/SYS/MY_KOBJ1. As mentioned earlier, Kobject also provides the function of reference counting, although it is essentially leveraging kref, but it also provides additional interfaces for users 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 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 the kobject from the plant model and the corresponding directories in the 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, if you first release obj1 through Kobject_put, the Kobject_del (&obj2->kobj) will have a memory error. */module_init (Mykobj_init); Module_exit (Mykobj_exit); Module_license ("GPL");

Source code Download


2. Structural Improvement

in this implementation, we set up two objects obj1 and Obj2,obj1 are the parent of obj2, and if spread out, obj1 can have more sub-objects. In the Linux kernel, this kind of architecture is actually not much practical value, one of the limited use is to create subdirectories in the SYSFS (the Linux kernel has this kind of usage, in this case, directly call the kernel provided by the kobject_create to implement, There is no need to customize the data structure and embed kobject), and there are other ways to create subdirectories . We know that the original purpose of the Linux device model was to facilitate power management, which required a traversal from top to bottom, in which all its child objects could not be accessed through obj1. The biggest implication of this practice is that we can clearly understand 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 access rights of the file};struct attribute val_attr = {. Name = "Val",//file name. Mode = 0666,//Specify the access rights of the file};struct attribut E *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 rights to the files. 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 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 used to initialize the Kobject structure, Kobject_add is used to add kobj to the device model. In the implementation, we first initialize and add to the Obj1 action, the invocation parameter, the parent is assigned to NULL, indicating that obj1 no parent object, reflected in the SYSFS, My_kobj1 directory will appear in/sys, Obj2 's parent object is set to Obj1, then My_ The Kobj2 directory will appear under/SYS/MY_KOBJ1. As mentioned earlier, Kobject also provides the function of reference counting, although it is essentially leveraging kref, but it also provides additional interfaces for users 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 directories in the 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 these two functions call kobject_get to increase the parent objectReference count, so Kobject_del needs to call Kobject_put to reduce the reference count of the parent object. In this example, if you first release obj1 through Kobject_put, 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 add obj1 and obj2. It is important to note that the parent in the Kobject_init_and_add parameter is null, in which case, obj1 and Obj2 are determined by the Kset pointer in the KOBJECT structure, which is my_kset in this practice. In Module_exit, we also need to call Kset_unregister to release the My_kset we created earlier.




Kobject embedded structure of Linux device model

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.