Char Devices
Linux character devices are a fundamental component of the kernel's device driver model, enabling communication with hardware that requires sequential data transfer. Unlike block devices (which handle random access to data blocks), character devices operate on a stream of bytes, making them ideal for devices like keyboards, serial ports, and sensors. Understanding their implementation is critical for kernel module development, as they form the basis for many peripheral interactions.
Device Numbers and Registration¶
Every character device is uniquely identified by a device number, a 32-bit value split into major and minor components. The major number identifies the driver responsible for the device, while the minor number distinguishes between multiple instances of the same driver (e.g., multiple serial ports).
Creating Device Numbers¶
Device numbers are created using the MKDEV() macro or make_dev_t() function:
dev_t type is defined in <linux/kdev_t.h>, and the /proc/devices file lists all registered major numbers.
Registering Devices¶
To register a character device, use register_chrdev_region() or alloc_chrdev_region():
int ret = register_chrdev_region(dev_num, 1, "my_char_dev");
if (ret < 0) {
printk(KERN_ERR "Failed to register device\n");
return ret;
}
Character Device Drivers¶
A character driver implements the file_operations structure, defining callbacks for I/O operations:
struct file_operations fops = {
.open = my_open,
.read = my_read,
.write = my_write,
.release = my_release,
};
open(): Initializes device-specific data (e.g., allocating buffers).
- read()/write(): Handles data transfer, often using copy_to_user()/copy_from_user().
- release(): Cleans up resources when the device is unopened.
Synchronization and Locking¶
Drivers must protect against race conditions using mutexes or spinlocks. For example:
static DEFINE_MUTEX(my_mutex);
int my_open(struct inode *inode, struct file *file) {
mutex_lock(&my_mutex);
// Device-specific initialization
mutex_unlock(&my_mutex);
return 0;
}
Role in Linux System Architecture¶
Character devices bridge user-space applications and hardware, enabling direct interaction with peripherals. They are essential for: - Input devices (keyboards, mice) - Serial communication (RS-232 ports) - Custom hardware (e.g., sensors, GPIO interfaces)
Unlike block devices, character devices do not cache data, ensuring real-time responsiveness. They are also used in device drivers for virtual devices (e.g., /dev/zero or /dev/random).
Key takeaways¶
- Character devices use major/minor numbers to map to drivers and instances.
- Device registration requires
register_chrdev_region()oralloc_chrdev_region(). - The
file_operationsstructure defines driver behavior for I/O operations. - Synchronization mechanisms like mutexes are critical for thread safety.
- Character devices enable direct, stream-based communication with hardware and virtual devices.