下面是一个Linux字符设备驱动开发的完整示例,以控制一个简单的LED设备为例。这个示例涵盖了驱动开发的核心流程:初始化、文件操作接口实现、用户空间交互等,适合理解驱动开发的基本框架。
示例:LED字符设备驱动 (Linux Kernel Module)
功能描述
- 通过驱动控制一个GPIO连接的LED。
- 用户空间通过
/dev/led_dev
写入
'1'
写入
'0'
读取设备返回当前LED状态。
代码实现
1. 驱动源码 (led_driver.c)
c
复制
下载
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/gpio.h> // GPIO控制头文件
#include <linux/errno.h>
#define DEVICE_NAME "led_dev"
#define LED_GPIO 21 // 假设LED连接在GPIO21
static dev_t dev_num;
static struct cdev led_cdev;
static struct class *led_class;
// 文件操作函数
static int led_open(struct inode *inode, struct file *file) {
return 0;
}
static ssize_t led_read(struct file *file, char __user *buf, size_t len, loff_t *offset) {
char state;
state = gpio_get_value(LED_GPIO) ? '1' : '0'; // 读取GPIO电平
if (copy_to_user(buf, &state, 1))
return -EFAULT;
return 1;
}
static ssize_t led_write(struct file *file, const char __user *buf, size_t len, loff_t *offset) {
char val;
if (copy_from_user(&val, buf, 1))
return -EFAULT;
if (val == '1')
gpio_set_value(LED_GPIO, 1); // 点亮LED
else if (val == '0')
gpio_set_value(LED_GPIO, 0); // 熄灭LED
else
return -EINVAL;
return 1;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
};
// 模块初始化
static int __init led_init(void) {
// 1. 申请设备号
alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);
// 2. 注册字符设备
cdev_init(&led_cdev, &fops);
cdev_add(&led_cdev, dev_num, 1);
// 3. 创建设备节点 (/dev/led_dev)
led_class = class_create(THIS_MODULE, "led_class");
device_create(led_class, NULL