Usage of ktype in Linux Device Model

Source: Internet
Author: User

Author:Liu Hongtao, senior lecturer of Huaqing vision embedded College, and an expert of arm authorized by ATC.

In the previous article "using udev and sys to dynamically create device nodes", the device driver mainly relies on the following two functions:

1. Create the farsight_class class under/sys/class.

My_class = class_create (this_module, "farsight_class ");

2. Create a Class Device in farsight_class

Class_device_create (my_class, null, devno, null, "farsight_dev ");

The file structure shown in/sys is as follows:

 

Both "Dev" and "uevent" are "attributes". You can read Dev to obtain the Primary and Secondary device numbers of the device. You can also operate on uevent, and send the "add" event to the kernel for hot swapping. For example:

 

Note: writing any value here will lead to the "add" event. The udevmonitor detection symptom is as follows:

Uevent [1220019773.507374] add ????? /Class/farsight_class/farsight_dev (farsight_class)

So what is the principle of the above functions? Now, we need to over-use the topic ktype in this article. First, let's get to know this structure.

The structure of kype is defined:

Struct kobj_type {
Void (* release) (struct kobject *);
Struct sysfs_ops * sysfs_ops;/* provides methods to implement the following attributes */
Struct attribute ** default_attrs;/* used to save the type attribute list (pointer )*/
};

Attribute is defined:

Struct attribute {
Char * Name;/* attribute name (displayed in the sysfs directory of kobject, such as Dev and uvent )*/
Struct module * owner;/* pointer to the module (if any), this module is responsible for implementing this attribute */
Mode_t mode;/* attribute protection bit. The modes macro is defined in <Linux/STAT. h>. For example, s_irugo is a read-only attribute */
};/* The last element in the default_attrs list must be filled with 0 */

In sysfs, attribute read/write is performed by functions in kobj_type-> sysfs_ops:

Struct sysfs_ops {
Ssize_t (* Show) (struct kobject * kobj, struct attribute * ATTR, char * buffer );
Ssize_t (* store) (struct kobject * kobj, struct attribute * ATTR, const char * buffer, size_t size );
};

When a user space reads an attribute (for example, # Cat Dev), the kernel calls the show method using the pointer to kobject (kobj) and the correct attribute structure (* ATTR, this method encodes the given property value into the buffer (note not to cross-border (page_size byte) and returns the actual data length.

You can also use the same show Method for attributes associated with all kobject (usually within the range of a kset Association) and use the ATTR pointer passed to the function to determine the Requested attribute. Some show methods include checking the attribute name. Some show Methods embed the property structure into another structure (this method is used in the example in this article). This structure contains information about the property values to be returned, in this case, container_of can be used to obtain the pointer of the Upper-layer structure to return the attribute value information.

When a user space writes an attribute (such as Echo "hello"> event), the kernel uses the pointer to kobject (kobj) and the correct attribute structure (* ATTR) to call the store method.

The store method decodes cached data (the size is the length of the data and cannot exceed page_size), saves the new value to the attribute (* ATTR), and returns the actual number of decoded bytes. The store method can be called only when the write permission of an attribute is available. Note: to receive data from a user space, verify its validity. If the data does not match, a negative error value is returned.

Each kobject requires an associated kobj_type structure. The pointer to this structure can be found in two different places:

(1) The kobject structure itself contains a member (ktype) pointing to kobj_type;

Struct kobject {
......
Struct kobj_type * ktype;/* pointer to struct kobj_type that tracks the kobject type */
......
}

(2) If this kobject is a member of a kset, kset provides the kobj_type pointer.

Struct kset {
Struct kobj_type * ktype;/* pointer to the kset object type */
......
}

Which of the following is used to access the attribute?Kobj_typeWhat about it?

The following function is used to find the kobj_type pointer of a specified kobject:

Static inline struct kobj_type * get_ktype (struct kobject * K)
{
If (k-> kset & K-> kset-> ktype)
Return K-> kset-> ktype;
Else
Return K-> ktype;
}

As shown above, ksetKtype inThis type takes precedence over kobjectKtype in itself. Therefore, in typical applications, the ktype member in struct kobject is set to null, while the ktype in kset is actually used.

The following describes how to use ktype by tracking class_device_create (my_class, null, devno, null, "farsight_dev.

1,

Struct class_device *Class_device_create(......)
{
......
Retval =Class_device_register(Class_dev );
}

2,

IntClass_device_register(Struct class_device * class_dev)
{
Class_device_initialize(Class_dev );
Return class_device_add (class_dev );
}

3,

VoidClass_device_initialize(Struct class_device * class_dev)
{
Kobj_set_kset_s(Class_dev,Class_obj_subsys);
Kobject_init (& class_dev-> kobj );
Init_list_head (& class_dev-> node );
}

4,

# DefineKobj_set_kset_s(OBJ, subsys )/
(OBJ)-> kobj. kset = & (subsys). kset
We can see that the name is"Farsight_dev"The corresponding kset of kobject is class_obj_subsys.kset.

5,

LookClass_obj_subsysDefinition
Static decl_subsys (class_obj, & ktype_class_device, & class_uevent_ops );

# Define decl_subsys (_ name, _ type, _ uevent_ops )/
Struct subsystem _ name ##_ subsys = {/
. Kset = {/
. Kobj = {. Name = _ stringify (_ name )},/
. Ktype = _ type ,/
. Uevent_ops = _ uevent_ops ,/
}/
}

Therefore, the ktype corresponding to the kset isKtype_class_device

6,

Static struct kobj_typeKtype_class_device= {
. Sysfs_ops ????? = &Class_dev_sysfs_ops,
. Release ??? = Class_dev_release,
};

7,

Static struct sysfs_opsClass_dev_sysfs_ops= {
. Show ???? =Class_device_attr_show,
. Store ????? =Class_device_attr_store,
};

This operation is used when you operate "Dev" or "uevent" in the preceding section.Class_dev_sysfs_ops

8,

Class_device_attr_show(Struct kobject * kobj, struct attribute * ATTR,
Char * BUF)
{
Struct class_device_attribute *Class_dev_attr=To_class_dev_attr(ATTR );
Struct class_device * Cd = to_class_dev (kobj );
Ssize_t ret = 0;
If (class_dev_attr-> show)
Ret =Class_dev_attr-> show (Cd, Buf);
Return ret;
}

Class_device_attr_store(Struct kobject * kobj, struct attribute * ATTR,
Const char * Buf, size_t count)
{
Struct class_device_attribute *Class_dev_attr=To_class_dev_attr (ATTR );
Struct class_device * Cd = to_class_dev (kobj );
Ssize_t ret = 0;
If (class_dev_attr-> store)
Ret =Class_dev_attr-> store (Cd, Buf, count );
Return ret;
}

It can be seen that the operation function willTo_class_dev_attr (ATTR); find the corresponding ATTRClass_dev_attrAnd call the corresponding showOr store

9,

Next, let's take a look at the definitions of Dev and uvent attributes and their corresponding operation functions.

ATTR-> ATTR. Name = "Dev ";
ATTR-> ATTR. mode = s_irugo;
ATTR-> ATTR. Owner = parent_class-> owner;
ATTR-> show = show_dev;
Error = class_device_create_file (class_dev, ATTR );

Static ssize_t show_dev (struct class_device * class_dev, char * BUF)
{
Return print_dev_t (BUF, class_dev-> devt );//"252:0"
}

Class_dev-> uevent_attr.attr.name = "uevent ";
Class_dev-> uevent_attr.attr.mode = s_iwusr;
Class_dev-> uevent_attr.attr.owner = parent_class-> owner;
Class_dev-> uevent_attr.store = store_uevent;
Error = class_device_create_file (class_dev, & class_dev-> uevent_attr );

Static ssize_tStore_uevent(Struct class_device * class_dev,
Const char * Buf, size_t count)
{
Kobject_uevent (& class_dev-> kobj, kobj_add );
Return count;
}

It can be seen that the kobj_add event is triggered no matter what value is written. The kernel calls the kobject_uevent function to send the Netlink message to the user layer of the user space. The user space can use udev to obtain the event to handle hot swapping events.

Now, I have finished writing it. I hope it will be of reference value to you.

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.