3

I'm learning to write a simple kernel module that implements open, read, write, close, ioctl syscalls for reading/writing in kernel memory (something like a shared memory / IPC demo).

I used to call mknod for binding the major/minor number allocated by the driver with a character file. But I questioned myself about why we aren't always required to manually do so when we attach an USB pendrive to the system, and I discovered udev.

I know how to use kobject_init_and_add() and kobject_uevent() to create a node in sysfs tree and notify udev, but while exploring /sys folder I noticed the /sys/dev/char folder, that contains symlinks to devices, named like major:minor. I don't understand why I can't find here the major/minor couple of my driver... Am I supposed to manually do something else from inside the module?

How can I find a full-but-simple example on how to properly describe and handle my "virtual" device in the sysfs tree?

1 Answers1

4

After reading Chapter 4 of "Linux device driver development" by John Madieu, I discovered that it was easier than what I thought:

all you need in order to automatically instantiate the proper character device abstractions in /sys and /dev is to create a struct class with the help of class_create(...) function, and then use device_create(...).

Effects: assuming you have a class called my_class and call the device my_device with major number xx and minor number yy,

  • /sys/class/my_class folder is created;
  • /sys/devices/virtual/my_class/my_device folder is created;
  • /sys/class/my_class/my_device symlink points to /sys/class/my_class/my_device;
  • /sys/dev/char/xx:yy symlink points to /sys/class/my_class/my_device;
  • /dev/my_device character device is created (so no more mknod calls);

The /sys/class/my_class/my_device folder is quite interesting. It has:

  • dev file: it contains major:minor number;
  • uevent file: if you write add in it, the kernel will re-emit add uevents; uevents are used to signal a userspace daemon like udev about creation/modification/removal of a kernel object in the sysfs tree;
  • subsystem symlink: it points back to /sys/class/my_class;
  • power folder: probably some interfaces for stuff like this.

Always remember to match every *_create call with a *destroy call in the exit function of the module.

class_create, class_destroy, device_create, device_destroy are declared in include/linux/device.h and defined respectively in drivers/base/class.c and drivers/base/core.c (paths in kernel source tree). There's good documentation in those source files.