Kobject, kset, sub-system hierarchy
The kernel usually uses the kobject structure to connect each object to form a hierarchical structure system.
Parent is a pointer to another kobject structure (a node in the upper layer of the hierarchy). It is mainly used to locate objects in the sysfs hierarchy.
A kset is a set of kobject embedded into the same type structure. However, struct kobj_type focuses on the object type, while struct kset focuses on the object set. It can be considered that kset is the top-level container class of kobjects. Each kset contains its own kobject, and can be processed in multiple ways. Kset always appears in sysfs. Once a kset is set and added to the system, a directory is created in sysfs. kobjects does not need to be expressed in sysfs, however, each kobject member in the kset is expressed in sysfs.
Add kobject to kset. It is usually completed when kobject is created. The process is divided into three steps:
(1) initialize kobject. Pay special attention to entry and parent initialization.
(2) point the kset member of kobject to the target kset.
(3) pass kobject to the following function:
Int kobject_add (struct kobject * kobj);/* The function may fail (a negative error code is returned), and the program should respond accordingly */
The kernel provides a composite function:
Extern int kobject_register (struct kobject * kobj);/* It is only a combination of kobject_init and kobject_add. Initialization of other Members must be completed manually */
When you delete a kobject from the kset to clear the reference:
Void kobject_unregister (struct kobject * kobj);/* is the combination of kobject_del and kobject_put */
Kset stores its child nodes in a standard kernel linked list. In most cases, the included kobjects saves the pointer to the kobject embedded in kset in their parent members, the link is as follows:
All included kobjects in the chart are actually embedded in some other types, or even other ksets.
Ksets have interfaces similar to kobjects initialization and setting.
Ksets also has a pointer pointing to the kobj_type structure to describe the kobject it contains. This type prevails over the ktype in the kobject itself. Therefore, in typical applications, the ktype member in struct kobject is set to null, while the ktype in kset is actually used.
In the new kernel, kset no longer contains a sub-system pointer struct subsystem * subsys, And the subsystem has been replaced by kset.
Subsystem is a description of some advanced components of the entire kernel. Subsystems usually appear at the top layer of the sysfs hierarchy. kernel subsystems include block_subsys (/sys/block device) and devices_subsys (/sys/devices core device layer) and specific subsystems known to the kernel for various bus.
The new kernel no longer has the subsystem data structure, instead of kset. Each kset must belong to a subsystem. subsystem members help the kernel locate the kset in the hierarchy.
/* Subsystems generally use the following macro Description: * // Linux/lib/kobject. h
185 # define decl_subsys (_ name, _ type, _ uevent_ops )/
186 struct kset _ name ##_ subsys = {/
187. kobj = {. Name = _ stringify (_ name )},/
188. ktype = _ type ,/
189. uevent_ops = _ uevent_ops ,/
190}
/* Subsystem operation functions :*/
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 basically the packaging of kset operation functions to implement Sub-system operations */
For example: void subsystem_init (struct kset * s); In/Linux/lib/kobject. c
659int subsystem_register (struct kset * s)
660 {
661 return kset_register (s );
662}
Kobject is a mechanism after the sysfs Virtual File System. Each directory in sysfs has a corresponding kobject in the kernel. Each kobject outputs one or more attributes. It appears as a file in the sysfs directory of kobject, And the content is generated by the kernel.
Sysfs File System explanation: http://blog.chinaunix.net/u1/55599/showart_1089096.html
Sysfs. H source code analysis: http://blog.chinaunix.net/u1/55599/showart_1091002.html
The entry to create a kobject in sysfs is part of the kobject_add job. If you call kobject_add, it will be displayed in sysfs. Some knowledge is worth remembering:
(1) The sysfs entry of kobjects is always a directory. The call of kobject_add will create a directory in sysfs, which contains one or more attributes (files );
(2) the name assigned to kobject (using kobject_set_name) is the directory name in sysfs. The kobjects that appears in the same part of the sysfs hierarchy must have a unique name. the names assigned to kobjects should also be valid file names: they cannot contain illegal characters (such as diagonal lines) and are not recommended to use blank spaces.
(3) The sysfs entry position corresponds to the parent pointer of the kobject. If parent is null, it is set to kobject embedded in the kset of the new kobject. If parent and kset are both null, The sysfs entry directory is in the top-level directory, which is generally not recommended.
When a kobject is created, each kobject is given a series of default attributes. These attributes are stored in the kobj_type structure:
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 )*/
};
Struct attribute {
Char * Name;/* attribute name (displayed in the sysfs directory of kobject )*/
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 */
Sysfs reads and writes these attributes by functions in the kobj_type-> sysfs_ops member:
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, the kernel uses the pointer to kobject (kobj) and the correct attribute structure (* ATTR) to call the show method, this method encodes the given property value into the buffer (note not to cross-border (page_size byte) and returns the actual data length. Sysfs conventions require that each attribute should contain a readable value. If a large amount of information is returned, it should be divided into multiple attributes.
You can also use the same show method for all attributes associated with kobject, 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 attribute structure into another structure, which contains information about the attribute 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.
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.
Although the default_attrs Member of the kobject type describes all attributes that kobject will possess, if you want to add a new attribute to the sysfs Directory attribute of kobject, you only need to simply fill in an attribute structure and pass it to the following functions:
Int sysfs_create_file (struct kobject * kobj, struct attribute * ATTR );
/* If successful, the file is created with the name in the attribute structure and 0 is returned; otherwise, the negative error code is returned */
/* Note: The kernel calls the same show () and store () functions to perform operations on new attributes. Therefore, before adding a new non-default attribute, necessary steps should be taken to ensure that these functions know how to implement this attribute */
To delete a property, call:
Int sysfs_remove_file (struct kobject * kobj, struct attribute * ATTR );
/* After the call, this attribute no longer appears at the sysfs entry of the kobject. If a user space process may have a file descriptor of the opened attribute, after the attribute is deleted, show and store may still be called */
Binary Attribute
Sysfs usually requires that all attributes contain only one value in the readable text format, and seldom needs to create attributes that can process a large amount of binary data. This feature is required when unchangeable data is transmitted between the user space and the device (for example, the firmware is uploaded to the device. The binary attribute is described using a bin_attribute structure:
Struct bin_attribute {
Struct attribute ATTR;/* attribute struct */
Size_t size;/* maximum size of the Binary Attribute (0 if no maximum value exists )*/
Void * private;
Ssize_t (* read) (struct kobject *, char *, loff_t, size_t );
Ssize_t (* write) (struct kobject *, char *, loff_t, size_t );
/* The read and write methods are similar to the character-driven read and write methods. The read and write methods can be called multiple times during a single load, and the maximum number of data pages can be operated at a time, you must be able to determine the end of the operation data in other ways */
INT (* MMAP) (struct kobject *, struct bin_attribute * ATTR,
Struct vm_area_struct * VMA );
};
/* The Binary Attribute must be explicitly created and cannot be created with the default attribute. Create a Binary Attribute called :*/
Int sysfs_create_bin_file (struct kobject * kobj, struct bin_attribute * ATTR );
/* Call to delete binary properties :*/
Int sysfs_remove_bin_file (struct kobject * kobj, struct bin_attribute * ATTR );
Symbolic Link
The sysfs file system has a tree structure that reflects the organizational hierarchy between kobject. To represent the relationship between the driver and the managed device, additional pointers are required, which are implemented through symbolic links in sysfs.
/* Create a symbolic link in sysfs :*/
Int sysfs_create_link (struct kobject * kobj, struct kobject * target, char * Name );
/* The function creates a link (name) pointing to the target's sysfs entry as an attribute of kobj. It is a relative connection and has nothing to do with its position in the sysfs system */
/* Delete the symbolic connection call :*/
Void sysfs_remove_link (struct kobject * kobj, char * Name );
Hot swapping event generation
A hot swapping event is a notification sent from the kernel space to the user space, indicating that the system configuration has changed. This event is generated no matter whether the kobject is created or deleted. Hot swapping events can cause/sbin/hotplug calls, which respond to events by loading drivers, creating device nodes, attaching partitions, or other correct actions.
The actual control of hot swapping events is implemented through a set of methods stored in the structure of kset_uevent_ops (struct kset_hotplug_ops * hotplug_ops introduced in ldd3; it has been replaced by the kset_uevent_ops struct in 2.6.22.2:
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, char ** envp,
Int num_envp, char * buffer, int buffer_size );
};
You can find the pointer to the kset_uevent_ops structure in the uevent_ops Member of the kset structure.
If the specified kset is not included in the kobject, the kernel searches in the layered structure through the parent pointer until a kobject containing the kset is found. Then, the kset hot swapping operation is used.
The three methods in the kset_uevent_ops structure have the following functions:
(1) The filter function allows the kset code to determine whether to pass the event to the user space. If the filter returns 0, no event is generated. Taking the disk filter function as an example, it only allows kobject to generate disk and partition events. The source code is as follows:
Static int block_hotplug_filter (struct kset * kset, struct kobject * kobj)
{
Struct kobj_type * ktype = get_ktype (kobj );
Return (ktype = & ktype_block) | (ktype = & ktype_part ));
}
(2) When a user space hot swapping program is called, the sub-system name will be passed to it as a unique parameter. The name function is responsible for returning suitable strings to the hot swapping program in the user space.
(3) Any other parameters obtained by the hot swapping script are passed through environment variables. The uevent function adds parameters to environment variables before calling the hot swapping script. Function prototype:
INT (* uevent) (struct kset * kset, struct kobject * kobj,/* target object that generates the event */
Char ** envp,/* an array that saves the definition of other environment variables (usually in name = value format */
Int num_envp,/* number of variables contained in the environment variable array (array size )*/
Char * buffer, int buffer_size/* pointer and number of cell lines (size) in the buffer after the environment variable is encoded )*/
/* If you need to add any environment variables to envp, you must add a null entry after the last entry to let the kernel know the end of the array */
);
/* The normal return value should be 0. If a non-zero value is returned, the hot swapping event will be terminated */
Hot swapping events are usually generated by the logic at the bus driver layer.
Article Source: DIY tribe (http://www.diybl.com/course/6_system/linux/Linuxjs/2008727/134055.html)