Transferred from http://blog.csdn.net/yj4231/article/details/7799245
In this paper, a simple analysis of the SYSFS in Linux system, to analyze the SYSFS must analyze the kernel of the Driver-model (drive model), the two are closely related. In the analysis process, this article will take the platform bus and the SPI main controller's platform drive as an example to explain. In fact, the platform mechanism is based on Driver-model, through this article, will also have a simple understanding of the platform mechanism.
Kernel version: 2.6.30 1. What is SYSFS.
Personal understanding: Sysfs shows the hierarchy of drive devices to user space. We all know that devices and corresponding drivers are managed by the kernel, which is not visible to user space. Now through SYSFS, you can intuitively understand the device-driven hierarchy in user space.
Let's look at the SYSFS file structure:
[Root@yj423/sys] #ls
Block Class devices FS module
Bus Dev firmware kernel power
Blocks: Block devices
Bus: Buses in the system
Class: Device type, such as input device
Dev: view of a registered device node in the system with two subdirectories char and block.
Devices: All device topology views in the system
Fireware: Firmware
FS: File System
Kernel: Kernel configuration options and status information
Module: Modules
Power: System Management data
2. Kobject, Kset and Ktype
To analyze Sysfs, first of all, we must analyze Kobject and kset, because the structure of the driver device hierarchy is done by these two dongdong. 2.1 Kobject
Kobject is an abstraction of an object that is used to manage objects. Each kobject corresponds to a directory in the SYSFS.
Kobject is described with struct kobject.[CPP] View Plain Copy struct kobject { const char *name; /* The name of the directory created in Sysfs */ struct list_head entry; /* used to connect to the Kset list */ struct kobject *parent; /* Parent Object */ struct kset *kset; /* belong to which kset*/ struct kobj_type *ktype; /* Type * * struct sysfs_dirent *sd;  The file node corresponding to the object in /*sysfs */ struct kref Application count of the kref; /* object * * 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; }; 2.2 Kset
Kset is a collection of kobject that can have the same ktype or different kobject. At the same time, Kset himself also contains a kobject. In Sysfs, Kset also corresponds to this directory, but the contents of the bread contain other kojbect.
Kset use struct kset to describe.[CPP] View Plain Copy/** * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. * * A kset defines a group of kobjects. They can be individually * different "Types" but overall these kobjects all want to be grouped * together and operated on in the same manner. ksets are used to * define the attribute callbacks and other common events that happen to * a kobject. * * @list: the list of all kobjects for this kset * @list_lock: a lock for iterating over the kobjects * @kobj: the embedded kobject for this kset (RECURSION, ISN ' T it fun ...) * @uevent_ops: the set of uevent operations for this kset. these are * called whenever a kobject has something happen to it so that the kset * can add new environment variables, or filter out the uevents if so * desired. */ struct kset { struct list_head list; /* belong to the Kset kobject linked list */ spinlock_t list_lock; struct kobject kobj; /* the Kset embedded kobj*/ struct kset_uevent_ops *uevent_ops; };
2.3 Ktype
Each Kobject object is embedded with a ktype that defines the behavior that Kobject takes when it is created and deleted.[CPP] View Plain copy struct kobj_type { void (*release) (struct Kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; }; struct sysfs_ops { ssize_t (*show) (struct kobject *, struct attribute *,char *); ssize _t (*store) (Struct kobject *,struct attribute *,const char *, size_t); }; /* fixme * the *owner field is no longer used. * x86 tree has been cleaned up. the owner * attribute is still left for Other arches. */ struct attribute { const char *name; struct module *owner; mode_t mode; }; when the Kobject reference count is 0 o'clock, Releasing the associated resources through the release method.
attribute is a property, each attribute has a corresponding property file in the Sysfs.
Sysfs_op's two methods are used to implement the behavior that should be taken when reading and writing property files. the relationship between 2.4 Kobject and Kset
The following picture is very classic. The bottom kobj belong to a kset, and the kobj of the parent object is the Kset embedded kobj. Through the list, Kset can get all the kobj that belong to it.
From the Sysfs point of view, Kset represents a folder, and the following kobj is the contents of the folder, and the content may be files and possibly folders.
3. For example
In the previous section, we know that there is a bus directory under SYS that will analyze how to create a bus directory through Kobject.
The following code is located in DRIVERS/BASE/BUS.C
[CPP] View plain copy int __init buses_init (void) { bus_kset = kset_create_and_add ("Bus", &bus_uevent_ops, null); if (!bus_kset) return -ENOMEM; return 0; } static struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; static int bus_uevent_filter (struct kset *kset, struct kobject *kobj) { Struct kobj_type *ktype = get_ktype (kobj); if (ktype == &bus_ktype) return 1; &nBsp return 0; } here directly call Kset_create_and_add, the first parameter is the name of the directory to be created, The third parameter indicates that there is no parent object.
The following code is located in drivers/base/kobject.c
[CPP] View Plain Copy/** * kset_create_and_add - create a struct kset dynamically and add it to sysfs * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @parent_kobj: the parent kobject of this kset, if any. * * this function creates a kset structure dynamically and registers it * with sysfs. When you are finished with this structure, call * Kset_unregister () and the structure will be dynamically freed when it * is no longer being used. * * if the kset was not able to be created, null will be returned. */ Struct kset *kset_create_and_add (const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; int error; kset = kset_create (name, uevent_ops, parent_kobj /* establish Kset, set some fields */ if (!kset) return NULL; error = Kset_register (kset); /* add Kset to sysfs*/ if (error) { kfree (kset); return NULL; } return kset; }
Here we call two functions, and then look at them separately. 3.1 kset_create function
The following code is located in drivers/base/kobject.c[CPP] View Plain Copy/** * kset_create - create a struct kset dynamically * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @ parent_kobj: the parent kobject of this kset, if any. * * This function creates a kset structure dynamically. This structure can * then be registered with the system and show up in sysfs with a call to * kset _register () . when you are finished with this structure, if * kset_register () has been called, call kset_unregister () and the * stRucture will be dynamically freed when it is no longer being used. * * if the kset was not able to be created, NULL will be returned. */ static struct Kset *kset_create (const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) { struct kset *kset; kset = kzalloc (sizeof (*kset), gfp_kernel);/* Assign kset*/ if (!kset) return null; kobject_set_name (&kset->kobj, name);/* Setting kobj->name*/ kset->uevent_ops = uevent_ops; kset->kobj.parent = parent_kobj; /* Set Parent object */ /* * the kobject of this kset will have a type of kset_ktype and belong to * no kset itself. That way we can properly free it when it is * finished being used. */ kset->kobj.ktype = &kset_ ktype; kset->kobj.kset = NULL; /* This keset does not belong to any kset*/ return kset; }
In this function, dynamically assign the Kset structure, call Kobject_set_name set kset->kobj->name for bus, which is the directory bus we want to create. And here kset->kobj.parent is null,
That is, there is no parent object. Because the bus directory to be created is created in the root directory where SYSFS resides, there is no parent object.
Then briefly look at the series of calls raised by the Kobject_set_name function call.[CPP] View Plain Copy/** * kobject_set_name - Set the name of a kobject * @kobj: struct kobject to set the name of * @fmt: format string used to build the name * * this sets the name of the kobject. if you have already added the * kobject to the system, you must call kobject_rename () in order to * change the name of the kobject. */ int kobject_set_name (Struct kobject *kobj, const char *fmt, ...) { va_list vargs; int retval; va_start (Vargs, fmt); retval = kobject_set_name_vargs (KOBJ, FMT, vargs); va_end (Vargs); return retval; } /** * kobject_set_name_vargs - set the name of an kobj