Tuesday, January 4, 2022

[SOLVED] cdev_alloc() vs cdev_init()

Issue

In Linux kernel modules, two different approaches can be followed when creating a struct cdev, as suggested in this site and in this answer:

First approach, cdev_alloc()

struct cdev *my_dev;
...
static int __init example_module_init(void) {
    ...
    my_dev = cdev_alloc();
    if (my_dev != NULL) {
            my_dev->ops = &my_fops;  /* The file_operations structure */
            my_dev->owner = THIS_MODULE;
        }
        else
                ...
}

Second approach, cdev_init()

static struct cdev my_cdev;
...
static int __init example_module_init(void) {
        ...
        cdev_init(&my_cdev, my_fops);
        my_cdev.owner = THIS_MODULE;
        ...
}

(assuming that my_fops is a pointer to an initialized struct file_operations).

  1. Is the first approach deprecated, or still in use?
  2. Can cdev_init() be used also in the first approach, with cdev_alloc()? If no, why?

The second question is also in a comment in the linked answer.


Solution

Can cdev_init() be used also in the first approach, with cdev_alloc()?

No, cdev_init shouldn't be used for a character device, allocated with cdev_alloc.

At some extent, cdev_alloc is equivalent to kmalloc plus cdev_init. So calling cdev_init for a character device, created with cdev_alloc, has no sense.

Moreover, a character device allocated with cdev_alloc contains a hint that the device should be deallocated when no longer be used. Calling cdev_init for that device will clear that hint, so you will get a memory leakage.


Selection between cdev_init and cdev_alloc depends on a lifetime you want a character device to have.

Usually, one wants lifetime of a character device to be the same as lifetime of the module. In that case:

  1. Define a static or global variable of type struct cdev.
  2. Create the character device in the module's init function using cdev_init.
  3. Destroy the character device in the module's exit function using cdev_del.
  4. Make sure that file operations for the character device have .owner field set to THIS_MODULE.

In complex cases, one wants to create a character device at specific point after module's initializing. E.g. a module could provide a driver for some hardware, and a character device should be bound with that hardware. In that case the character device cannot be created in the module's init function (because a hardware is not detected yet), and, more important, the character device cannot be destroyed in the module's exit function. In that case:

  1. Define a field inside a structure, describing a hardware, of pointer type struct cdev*.
  2. Create the character device with cdev_alloc in the function which creates (probes) a hardware.
  3. Destroy the character device with cdev_del in the function which destroys (disconnects) a hardware.

In the first case cdev_del is called at the time, when the character device is not used by a user. This guarantee is provided by THIS_MODULE in the file operations: a module cannot be unloaded if a file, corresponded to the character device, is opened by a user.

In the second case there is no such guarantee (because cdev_del is called NOT in the module's exit function). So, at the time when cdev_del returns, a character device can be still in use by a user. And here cdev_alloc really matters: deallocation of the character device will be deferred until a user closes all file descriptors associated with the character device. Such behavior cannot be obtained without cdev_alloc.



Answered By - Tsyvarev