Panel For Example Panel For Example Panel For Example

Common device registration functions in Linux

Author : Adrian January 21, 2026

 

Introduction

This article summarizes how to use the common Linux device-registration functions register_chrdev_region(), register_chrdev(), and alloc_chrdev_region().

 

Header file declarations

Functions for allocating, registering, and unregistering device numbers are declared in fs.h, as follows:

extern int register_chrdev_region(dev_t, unsigned, const char *); // Static allocation and registration of device number extern int alloc_chrdev_region(dev_t *, unsigned, const char *); // Dynamically allocate and register a device number extern int register_chrdev(unsigned int, const char *, struct file_operations *); // If first arg is 0 then dynamic, nonzero means static extern int unregister_chrdev(unsigned int, const char *); // Unregister device number extern void unregister_chrdev_region(dev_t, unsigned); // Unregister device number

 

Registering device numbers

Static registration

To use register_chrdev_region() you first define a dev_t variable to represent the device number:

dev_t dev_num;

To register a device you need a major device number.

Compose a device number from major and minor:

dev_num = MKDEV(major, minor); // major is the major device number, minor is the minor number

Register the device number:

register_chrdev_region(dev_num, 2, "dev_name");

The first argument is the device number, the second is the number of devices to register, and the third is the device name.

Dynamic registration

If the device number is not known in advance, request one dynamically:

alloc_chrdev_region(&dev_num, minor, 2, "dev_name");

The first argument returns the allocated device number, the second is the first minor number, the third is the count, and the fourth is the device name.

Retrieve the major number from a device number:

dev_major = MAJOR(dev_num);

 

Adding a character device to the kernel

struct cdev devno; cdev_init(&devno, &file_ops); // Initialize the cdev devno.owner = THIS_MODULE; // .owner indicates who owns this driver devno.ops = &mem_fops;

If the major number is known, add the device with:

cdev_add(&devno, dev_num, count);

If the device number was allocated dynamically, use:

cdev_add(&devno, MKDEV(mem_major, 0), count);

The first argument to cdev_add() is the device, the second is the device number, and the third is the number of minor devices to register. mem_major is the major number saved when allocated dynamically.

 

Unregistering devices

To unregister a device number, call:

unregister_chrdev_region(dev_t, unsigned);

The first argument must match the device number used when registering. If the device number was allocated dynamically, save it for later. The second argument is the count of minor devices.

 

 

Differences with register_chrdev()

Signature:

register_chrdev(unsigned int, const char *, struct file_operations *);

If the first argument is 0, the kernel dynamically allocates a major number for the driver. If nonzero, the driver requests a specific major number. The second argument is the device name and the third is the file_operations pointer. When dynamically allocated, the function returns the assigned major number.

Corresponding unregister function:

unregister_chrdev(unsigned int, const char *);

The first argument is the major number and must match the value used during registration. If the major number was allocated dynamically, save it for later. The second argument is the device name.

In summary, register_chrdev_region() differs from register_chrdev() by including the explicit step of registering a cdev with the kernel. register_chrdev_region() is effectively a more explicit version of register_chrdev().