This chapter teaches you how to write a misc device driver. Misc devices are a very common type of character device in the Linux kernel, suitable for various simple devices or tool-type drivers. It simplifies driver development, with tedious character device number management all handled by the kernel.
1. Misc Device Introduction
A misc device (misc device) is a special character device provided by Linux, using a unified major device number (generally 10), and distinguishing different devices through dynamically allocated minor numbers. It simplifies device number allocation and node creation device registration process.
Common misc devices in the /dev directory:
/dev/rtc/dev/uinput/dev/nvram- ... and more
Advantages:
- No need to allocate major device number yourself
- Simpler registration process
- Suitable for most common character device use scenarios
2. Misc Device Driver Structure
Mainly involves two structures and three operations:
struct miscdevice—— Misc device description structure (core)struct file_operations—— Device operation method table- Registration:
misc_register() - Unregistration:
misc_deregister()
3. Quick Writing of Misc Device Driver
Create a 08_misc_driver/ folder, and create a misc_driver.c file in it with the following code:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
// Device name
#define DEVICE_NAME "mymiscdev"
/* Device operation function table */
static ssize_t mymisc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_INFO "mymiscdev: read called\n");
return 0;
}
static ssize_t mymisc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_INFO "mymiscdev: write called\n");
return 0;
}
/* Device operation interface */
static struct file_operations mymisc_fops = {
.owner = THIS_MODULE,
.read = mymisc_read,
.write = mymisc_write,
};
/* Misc device description */
static struct miscdevice mymiscdev = {
.minor = MISC_DYNAMIC_MINOR, // Auto-allocate minor number
.name = DEVICE_NAME, // Name appearing under /dev
.fops = &mymisc_fops,
};
/* Called automatically when module is loaded */
static int __init mymiscdev_init(void)
{
int ret = misc_register(&mymiscdev);
if (ret)
printk(KERN_ERR "mymiscdev: register failed\n");
else
printk(KERN_INFO "mymiscdev: /dev/%s registered\n", DEVICE_NAME);
return ret;
}
/* Called automatically when unloading */
static void __exit mymiscdev_exit(void)
{
misc_deregister(&mymiscdev);
printk(KERN_INFO "mymiscdev: /dev/%s removed\n", DEVICE_NAME);
}
module_init(mymiscdev_init);
module_exit(mymiscdev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LCKFB");
MODULE_DESCRIPTION("misc device driver");2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1. Device name and header files
#define DEVICE_NAME "mymiscdev"Used to specify the device node name, final node will be /dev/mymiscdev.
2. Device operation functions (file_operations)
static ssize_t mymisc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_INFO "mymiscdev: read called\n");
return 0;
}2
3
4
5
.readand.writerespectively implement device read and write operations. Currently only print logs without exchanging data with users, returning 0 to indicate operation end.
3. file_operations structure
static struct file_operations mymisc_fops = {
.owner = THIS_MODULE,
.read = mymisc_read,
.write = mymisc_write,
};2
3
4
5
- Describes operations supported by this device (only basic read/write implemented here).
4. Misc device structure
static struct miscdevice mymiscdev = {
.minor = MISC_DYNAMIC_MINOR, // Auto-allocate minor number
.name = DEVICE_NAME, // Node name
.fops = &mymisc_fops, // Operation method table
};2
3
4
5
- This is the core structure for the kernel to manage misc devices.
- Set
minortoMISC_DYNAMIC_MINORfor auto-allocation. .name= the name appearing under/dev.
5. Driver load and unload
static int __init mymiscdev_init(void) {
return misc_register(&mymiscdev);
}
static void __exit mymiscdev_exit(void) {
misc_deregister(&mymiscdev);
}2
3
4
5
6
- Register device when loading (auto-generate
/dev/mymiscdev). - Unregister when unloading, node disappears.
4. Compilation and Testing
- Write
Makefile
export ARCH=arm64
# Cross compiler absolute path prefix
export CROSS_COMPILE=/home/lckfb/TaishanPi-3-Linux/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-
# Consistent with source file name
obj-m += misc_driver.o
# Kernel source directory
KDIR := /home/lckfb/TaishanPi-3-Linux/kernel-6.1
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
It's almost exactly the same as the Makefile we wrote before!
The only difference is it became misc_driver.o
CROSS_COMPILE: Still the compiler path prefix from the SDK.KDIR: Still the kernel source directory.
- Compile driver
Run in the 08_misc_driver/ directory:
makeIt will automatically generate the .ko file, which is what we need.
- Load module
Copy misc_driver.ko to the development board, mount the module, and you can see the device file we need generated under /dev:
sudo insmod misc_driver.ko5. Quick Q&A
- Q: What's the difference between misc device and regular character device driver? A: Regular character devices require you to allocate device numbers, manually register and create device nodes, while misc devices let the kernel automate everything, with less code and more convenience.
- Q: Does it support multiple misc devices? A: Yes, each device maintains its own independent
struct miscdevice. - Q: Where is the device node? A: Automatically created by the kernel under
/dev, with the name being the.namefield, such as/dev/mymiscdevin the example above.
6. Summary
- Misc device drivers greatly simplify the character device development process.
- Using
struct miscdeviceandmisc_register()can quickly complete a basic driver. - Suitable for beginners developing common small tools and component-type drivers.