Skip to content

Device Creation

Linux character devices are registered using alloc_chrdev_region(), which allocates a major number and creates device files in /dev. This function is essential for exposing custom hardware or virtual devices to user-space applications. The process involves allocating a device number range, registering the device, and ensuring proper cleanup on module removal.

Allocating a Device Number

The alloc_chrdev_region() function reserves a range of device numbers for your module. It takes four parameters:
- dev: A pointer to a dev_t variable where the allocated device number is stored.
- first_minor: The first minor number in the range (set to 0 for automatic assignment).
- num: The number of minor numbers to allocate.
- name: A string identifier for the device (used to create /dev/name entries).

Example:

dev_t dev;
int result = alloc_chrdev_region(&dev, 0, 1, "my_char_dev");
if (result < 0) {
    printk(KERN_ERR "Failed to allocate device number\n");
    return result;
}

Creating Device Files

The kernel automatically creates device files in /dev using the name parameter. For example, if name is "my_char_dev", the file /dev/my_char_dev is created. The major number is derived from dev using MAJOR(dev).

Unregistering the Device

When the module is removed, unregister_chrdev_region() frees the allocated device numbers:

void cleanup_module(void) {
    unregister_chrdev_region(dev, 1);
    printk(KERN_INFO "Device unregistered\n");
}

Example Code

Here’s a minimal module demonstrating the process:

#include <linux/fs.h>
#include <linux/module.h>

static dev_t dev;
static int __init my_char_dev_init(void) {
    int result = alloc_chrdev_region(&dev, 0, 1, "my_char_dev");
    if (result < 0) {
        printk(KERN_ERR "Allocation failed\n");
        return result;
    }
    printk(KERN_INFO "Device registered (major: %d)\n", MAJOR(dev));
    return 0;
}

static void __exit my_char_dev_exit(void) {
    unregister_chrdev_region(dev, 1);
    printk(KERN_INFO "Device unregistered\n");
}

module_init(my_char_dev_init);
module_exit(my_char_dev_exit);

Key takeaways

  • alloc_chrdev_region() allocates a major number and creates /dev entries automatically.
  • Always check for allocation errors and handle cleanup in exit functions.
  • The name parameter determines the device file name in /dev.
  • Device numbers are managed as dev_t values, combining major and minor components.
  • Manual mknod calls are unnecessary when using alloc_chrdev_region().