Linux sysfs System
1. Overview: What is sysfs?
<span>/sys</span> directory is a virtual file system provided by the kernel through the <span>sysfs</span> file system. It was introduced in the 2.6 kernel and is similar to <span>procfs</span> (<span>/proc</span>) but has different design purposes:
- • Purpose: To display the hierarchy of kernel objects (kobject), along with their attributes and relationships.
- • Content: It provides a structured view of information about devices, drivers, modules, kernel subsystems, etc.
- • Function:
- • Export kernel data to user space: Allows user space programs (like udev, utility scripts) to view and sometimes configure kernel parameters.
- • Foundation of the device model: Provides a unified model for device management (hotplugging, power management, device discovery).
- • Replace the chaotic /proc: Moves device-related information out of the unstructured
<span>/proc</span>, allowing<span>/proc</span>to focus more on process information.
A typical <span>/sys</span> directory contains the following subdirectories:
- •
<span>block/</span>: All block devices - •
<span>bus/</span>: All bus types in the system (e.g., pci, usb, i2c) - •
<span>class/</span>: Device classes categorized by function (e.g., net, sound, graphics) - •
<span>devices/</span>: Physical hierarchy of all devices in the system - •
<span>fs/</span>: Information related to file systems - •
<span>kernel/</span>: Kernel configuration and status information - •
<span>module/</span>: Information about loaded modules
2. Core Implementation Principles: kobject, kset, ktype
The implementation of sysfs is built on three core data structures that together form the foundation of the Linux device model.
a. kobject (Kernel Object)
- • What is it:
<span>struct kobject</span>is the most basic structure in the device model. It does not have an actual “device” meaning but serves primarily as a glue and reference counting base structure. - • Responsibilities:
- 1. Reference counting: Implemented through
<span>kref</span><span>, tracks the lifecycle of the object. When the reference count drops to 0, the object is released.</span> - 2. Representation in sysfs: Each
<span>kobject</span>corresponds to a directory in sysfs. - 3. Provides parent pointer: Used to establish hierarchy (directory structure) in sysfs.
- 4. Belonging relationship: Belongs to a certain
<span>kset</span><span> (set).</span>
b. kset (Kernel Object Set)
- • What is it:
<span>struct kset</span>is a collection of<span>kobject</span>s. It is also a<span>kobject</span>. - • Responsibilities:
- 1. Aggregate kobject: Groups kobjects with common characteristics together (e.g., all PCI devices form a set).
- 2. Manage sysfs directory: A kset also corresponds to a directory in sysfs, and all kobject directories it contains are sub-items of this directory. For example,
<span>/sys/bus/pci/devices/</span>is a kset that contains all PCI device kobjects. - 3. Support hotplug events: When a kobject is added to or removed from a kset, the kset is responsible for sending a uevent (hotplug event) to user space.
c. ktype (Kernel Object Type)
- • What is it:
<span>struct kobj_type</span>describes the behavior of a class of kobjects. Kobjects of the same type share the same set of operations. - • Responsibilities:
- 1. Release function: Defines how to release the memory occupied by a kobject when its reference count is 0. This is mandatory.
- 2. Default attributes: Provides the attribute files that this type of kobject has by default in sysfs (i.e., the
<span>show</span>and<span>store</span>operations). - 3. sysfs operations: Points to the
<span>sysfs_ops</span>structure, which contains the generic<span>show</span>and<span>store</span>methods for this type of kobject.
Summary of the relationships among the three:
- • A
<span>kobject</span>belongs to a<span>kset</span>. - • A
<span>kobject</span>has a<span>ktype</span>. - • A
<span>kset</span>also contains a<span>kobject</span>(thus it also has a directory in sysfs), and its internal kobjects can point to the same<span>ktype</span>(but this is not mandatory).
3. Code Framework and Key APIs
a. Creating and Initializing kobject
Typically, <span>kobject</span> is not used directly but is embedded in larger structures (like <span>struct device</span>, <span>struct device_driver</span>).
#include <linux/kobject.h>
/* 1. Initialize an already allocated kobject */
void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
/* 2. Register the kobject in the system and create its directory in sysfs */
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...);
/* 3. Usually combine initialization and addition into one function */
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
struct kobject *parent, const char *fmt, ...);
/* 4. Decrease reference count; when the count is 0, the object will be cleaned up */
void kobject_put(struct kobject *kobj);
/* Example code snippet */
struct my_device {
struct kobject kobj;
// ... other device-specific fields ...
};
static struct kobj_type my_ktype = {
.release = my_device_release,
.sysfs_ops = &my_sysfs_ops,
.default_attrs = my_default_attrs,
};
struct my_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) return -ENOMEM;
// Initialize and add to sysfs, parent object is kernel_kobj (/sys/kernel/)
ret = kobject_init_and_add(&dev->kobj, &my_ktype, kernel_kobj, "my_device");
if (ret) {
kobject_put(&dev->kobj);
return ret;
}
// Increase reference count to avoid accidental release
kobject_get(&dev->kobj);
b. Creating Attributes – Creating Files in sysfs
Attribute files are the interface for user space to interact with the kernel in sysfs.
There are two ways:
- 1. Default attributes: Provided through the
<span>default_attrs</span>field of ktype (these files are automatically created every time a kobject is created). - 2. Custom attributes: Dynamically created at runtime.
Attribute definition:
/* An attribute corresponds to a file in sysfs */
struct attribute {
const char *name; // File name
umode_t mode; // Permissions (e.g., 0644)
};
/* Usually use a richer attribute structure that includes read/write methods */
struct kobj_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count);
};
Creating and Destroying Attribute Files:
/* Create/remove an attribute file in the kobject's directory */
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
Show and Store Methods:
/* show: Read data from the kernel to user space (called when cat the file) */
static ssize_t my_attr_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
// ... fill data into buf ...
return strlen(buf);
}
/* store: Write data from user space to the kernel (called when echo > file) */
static ssize_t my_attr_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
unsigned long value;
int ret;
ret = kstrtoul(buf, 10, &value);
if (ret < 0)
return ret;
// ... use value ...
return count;
}
/* Define an attribute macro */
static struct kobj_attribute my_attr = __ATTR(my_value, 0664, my_attr_show, my_attr_store);
// Create it in the initialization code
sysfs_create_file(&dev->kobj, &my_attr.attr);
4. Implementation Process Summary (Using Virtual Device as an Example)
- 1. Define data structure: Create a structure that includes
<span>struct kobject</span>. - 2. Define ktype: Implement the
<span>release</span>method,<span>sysfs_ops</span>, and optional<span>default_attrs</span>. - 3. Allocate and initialize: Allocate memory for the structure and call
<span>kobject_init_and_add</span>. - 4. Create attribute files: Use
<span>sysfs_create_file</span>or automatically create through<span>default_attrs</span>. - 5. User space interaction: User space interacts with sysfs files through
<span>cat</span>and<span>echo</span>, triggering the<span>show</span>and<span>store</span>functions in the kernel. - 6. Cleanup: Reduce the reference count through
<span>kobject_put</span>, triggering the<span>release</span>method to free resources and automatically remove the directory from sysfs.
5. Interaction with User Space: uevent
When the device state changes (such as adding or removing), the kernel sends a uevent notification to user space (like <span>udevd</span>).<span>udevd</span> will dynamically create/delete device nodes (<span>/dev/</span>) based on these events and the information in <span>/sys</span>.
- • Trigger:
<span>kobject_uevent(&kobj, KOBJ_ADD)</span>or<span>KOBJ_REMOVE</span>. - • Information source: Information in the uevent environment variables (like device path
<span>DEVPATH</span>) mainly comes from the path of the kobject in sysfs.
Summary
| Kernel Concept | Sysfs Representation | Function || :— | :— | :— ||kobject|Directory| Basic building block, provides reference counting and hierarchy ||kset|Directory containing multiple subdirectories| Collection management, hotplug event distribution ||ktype|File operations in the directory| Defines the behavior of object types (release, default attributes) ||attribute|File in the directory| Data interface, allows user space to read/write kernel data |
The entire implementation of sysfs is an excellent example of object-oriented design, which presents the complex relationships among devices, buses, and drivers within the kernel in a clear directory tree format to user space through the three core structures: <span>kobject</span>, <span>kset</span>, and <span>ktype</span>.