Kernel Objects and Sysfs The /proc filesystem emerged as a superb tool during the development of the 2.4 kernel series. It provided “instant” access to and control of kernel parameters in a user friendly manner such that by simply using “cat” and “echo” kernel features could be examined and manipulated. Lack of documentation and a non unified structure caused a some what haphazard application of this excellent feature. An attempt was made in the 2.4 kernel to provide a more uniform approach to the concept using the SYSCTL interface. The 2.6 kernel permitted a major change to the whole infrastructure and produced what is called sysfs. Tightly coupled with the sysfs are things called kernel objects (more about those soon) A brief Overview of Sysfs Sysfs is a ram based file system like procfs. It allows kernel structures to be exported and their attributes and relationships to be visible from userspace. In fact it has all of the good features of the proc interface but with formal structure and documentation. The only possible drawback to the system is the large amount of memory it takes to hold the in memory filesystem. This problem is being addressed in recent kernel patches. Here is an overview of sysfs features Sysfs is a dynamic system allowing run time events to modify the system. Every Kobject is a directory in sysfs Every Kobject is a child of a subsystem An object's attributes are exposed as regular files in the object's directory. Attributes an be read from or written to using sysfs. The process of registering a kobject will also create an entry in sysfs. Sysfs will implement a hierarchy for a object providing parents, subsystem, and type definitions. The subsystem can include links to show how devices are related. Mounting Sysfs The following command will mount the sysfs on a 2.6 system mount -t sysfs sysfs /sys Normally this is done in the /etc/rc file. Some sysfs examples A tree view of a hard disk in sysfs. /sys |-- block | |-- hda | | |-- dev | | |-- device -> ../../devices/pci0000:00/0000:00:07.1/ide0/0.0 | | |-- hda1 | | | |-- dev | | | |-- size | | | |-- start | | | `-- stat | | |-- queue | | | |-- iosched | | | | |-- antic_expire | | | | |-- est_time | | | | |-- read_batch_expire | | | | |-- read_expire | | | | |-- write_batch_expire | | | | `-- write_expire | | | |-- nr_requests | | | `-- read_ahead_kb | | |-- range Looking at some of the elements >cat /sys/block/hda/hda2/start 208845 >cat /sys/block/hda/hda2/dev 3:2 >cat /sys/block/hda/queue/nr_requests 128 >cat /sys/block/hda/queue/iosched/est_time 18 % exit probability 1 ms new thinktime 1056767 sectors new seek distance Sysfs Documentation Unlike the older proc file system the sysfs and associated kernel objects do have some documentation and a reference design to look at. Documentation: ./Documentation/filesystems/sysfs.txt * ./Documentation/kobject.txt Reference Example: linux/drivers/block/genhd.c Kernel Objects Introduction The Kernel Object subsystem is complex. This is an attempt to understand the basics. The key feature of a kernel object is the concept of a reference count. The creator of an object can delete that object at any time but any users of that object will cause the object to remain in the system until its reference count falls to zero. At that time the object will be deleted. The Kernel Object Players The Kernel object basic structure is shown The Kernel Object Elements In general a Kernel Object needs the following elements k_name - The kernel name refcount - a count of processes using the object entry - a list Parent - a parent object name - the object's name type - this defines the attributes for an object set - this is a set of objects that belong to a specific subsystem Dentry - this is the reference to the object in the ram disk system Major Components The Major Components used in understanding the Kernel Object System are: kobjects - directories that appear in the sysfs file system . kset - a group of objects of a certain type. ktype - a group of helper functions for an object subsystem - the controller for a number of ksets. Use Overview In general, when using an object the flow is… Define a type that tells the system the object attributes and the release function to delete the object. Create a set of objects of the same type belonging to the same subsystem. The set object will be the object's parent. Each set has a object type that defines the subsystem and a type that defines the type of objects contained in the set. Create a subsystem to act as the root directory ( or use an existing one ) Create the object and fill in the name, parent, set and type fields Register the object (which adds it to the sysfs). Kset Overview A Kset belongs to a subsystem, it has a type, a list of members and also contains a kobject of its own. Ksets also participate in helping with hotplug operations by specifying a hotplug name and adding items to the hotplug helper's environment. Ktype Overview A Ktype defines the show and store operations that can be performed on the objectit also sets up the default attributes for the object. Subsystem Overview This is a base level system it has a kset whose kobject allows the subsystem to be placed in the system hierarchy properly. Confused ?? An example will show the basic mechanics of setting up a small subsystem. Remember Kobjects determine the position in the file system The KSET glues a kset to a subsystem Kernel Object / Sysfs Example The example discussed will show the basics of setting up a subsystem of a single type of object with attributes. The Computer Object The important kernel entity here is the kobject, the attributes are defined by the use of the object. // // Step 1 define an object // struct computer { struct kobject kobj; /* contains the name is also the directory entry */ /* user defined attributes follow */ char make[16]; char ip[16]; int speed; int capacity; int used; }; Define the attributes The attributes of the object will appear as regular files permissions and names need to be set at this stage. The only other element in the attribute structure is the module owner. Note that no show / store access functions are defined in basic attributes. /* * Step 2 define its attributes */ #define COM_MODE ( S_IRUGO | S_IWUGO ) static struct attribute computer_attr_make ={.name="make",.mode=COM_MODE }; static struct attribute computer_attr_ip ={.name="ip", .mode=COM_MODE }; static struct attribute computer_attr_speed={.name="speed",.mode=COM_MODE }; static struct attribute computer_attr_capacity={.name="capacity",.mode=COM_MODE}; static struct attribute computer_attr_used = {.name="used",.mode=COM__MODE }; /* * Now build an attribute structure as a null terminated list */ static struct attribute* computer_default_attrs[] = { &computer_attr_make, &computer_attr_ip, &computer_attr_speed, &computer_attr_capacity, &computer_attr_used, NULL }; Define the object type The sysfs_ops table will contain the show and store routines The release routine will tell the system how to remove the object. The type also defines the default attributes for the object. /* * Now we can define the type */ static struct kobj_type computer_ktype = { .release = computer_release, .sysfs_ops = &computer_sysfs_ops, .default_attrs = computer_default_attrs }; Define the subsystem type The subsystem type simply contains the notifier and clean up routine used when the system is deleted. Again the sysfs_ops table will contain the show and store routines The release routine will tell the system how to remove the object. The type also defines the default attributes for th object. static struct kobj_type sysfs_computer_ktype = { .release = sysfs_computer_release, .sysfs_ops = NULL, .default_attrs = NULL }; Define the Set In this example a static definition is used for a set. All the generated objects will be added to this set which will also be used by the subsystem to find its components. static struct kset computer_set; Declare the Subsystem The decl_subsystem helper function can be used here /* The following macro completes the definition of the subsystem */ decl_subsys(sysfs_computer, &sysfs_computer_ktype, 0 ); or by hand .. struct subsystem sysfs_computer_subsys = { .kset = { .kobj = { .name = __stringify(sysfs_computer) }, .ktype = &sysfs_computer_ktype, .hotplug_ops =0 } }; Define the KSET The KOBJECT SET is the key to the whole system char * name = "computers"; kobject_set_name(&computer_set->kobj, "%s", name); // associate the set with a subsystem computer_set->subsys = &sysfs_computer_subsys; // define the type of the set computer_set->kobj.ktype = &sysfs_computer_ktype; // define the type of objects contained in the set computer_set->ktype = &computer_ktype; // No hotplug for this object computer_set->hotplug_ops = NULL; // register the set to make it appear kset_register(computer_set); Register the Subsystem This will make sysfs aware of the subsystem. subsystem_register(&sysfs_computer_subsys); Initialize each object's system components This sets up the object in the sysfs hierarchy // create a new computer struct computer * computer = (struct computer*)kmalloc( sizeof(struct computer),GFP_KERNEL); if ( NULL == computer ) return NULL; memset(computer, 0x00, sizeof(struct computer)); kobject_set_name(&computer->kobj, "%s" , name); computer->kobj.parent = &computer_set.kobj; computer->kobj.kset = &computer_set; computer->kobj.ktype = computer_set.ktype; Initialize each object's attributes Having established the object's place in the hierarchy now set its attributes. strncpy(computer->make,make,16); strncpy(computer->ip,ip,16); computer->speed = speed; computer->capacity = capacity; computer->used = used; Register the object This step will expose the object to the sysfs system. kobject_register(&computer->kobj);

Clean up

This step will remove object from the sysfs system. struct kobject * kobj = NULL; while(!list_empty(&computer_set.list)) { kobj = (struct kobject *) list_entry(, struct kobject, entry); kobject_unregister(kobj); } kset_unregister(&computer_set); subsystem_unregister(&sysfs_computer_subsys); The system in action Here is an example of this system in action /sys/sysfs_computer/ `-- computers |-- comp_node_0 | |-- capacity | |-- ip | |-- make | |-- speed | `-- used […] `-- comp_node_4 |-- capacity |-- ip |-- make |-- speed `-- used