驱动_编写三个文件设备,每个设备文件绑定一个LED灯,当操作这个设备文件时只能控制设备文件对应的这盏灯
发布人:shili8
发布时间:2025-03-15 01:47
阅读次数:0
**驱动编写: 三个文件设备**
在本文中,我们将学习如何编写三个文件设备,每个设备文件绑定一个LED灯。当操作这个设备文件时,只能控制设备文件对应的这盏灯。
### 设备描述我们将创建三个设备文件:`led0`, `led1` 和 `led2`。每个设备文件都绑定一盏LED灯,分别是红色、绿色和蓝色LED灯。
### 设备驱动程序结构我们的设备驱动程序将包含以下几个部分:
* **led_driver.c**:这是设备驱动程序的主文件,它负责初始化设备、注册设备文件以及处理设备操作。
* **led0_driver.c**, **led1_driver.c** 和 **led2_driver.c**:这些文件分别负责控制红色、绿色和蓝色LED灯。
### 设备驱动程序代码#### led_driver.c
c#include#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); // 设备文件的 major 和 minor 号#define LED_MAJOR240#define LED_MINOR0// 设备文件的数量#define NUM_LEDS3// 设备驱动程序的结构体struct led_driver { struct cdev *cdev; }; // 设备驱动程序的函数指针数组static int (*led_ops[NUM_LEDs])(struct file *, void *); // 设备驱动程序的初始化函数static int __init led_init(void) { // 注册设备文件 if (alloc_chrdev_region(&led_major,0, NUM_LEDS, "led_driver") < 0) { printk(KERN_ERR "Failed to allocate device region "); return -1; } // 初始化设备驱动程序的结构体 struct led_driver *led = kmalloc(sizeof(struct led_driver), GFP_KERNEL); if (!led) { printk(KERN_ERR "Failed to allocate memory for led driver "); return -1; } // 注册设备文件 cdev_init(&led->cdev, &led_fops); led->cdev->owner = THIS_MODULE; // 添加设备文件到系统中 if (cdev_add(led->cdev, LED_MAJOR,0) < 0) { printk(KERN_ERR "Failed to add device file "); return -1; } // 初始化LED灯的驱动程序 led_ops[0] = &led0_init; led_ops[1] = &led1_init; led_ops[2] = &led2_init; return0; } // 设备驱动程序的卸载函数static void __exit led_exit(void) { // 删除设备文件 unregister_chrdev_region(LED_MAJOR, NUM_LEDS); //释放LED灯的驱动程序 kfree(led_ops[0]); kfree(led_ops[1]); kfree(led_ops[2]); return; } module_init(led_init); module_exit(led_exit);
#### led0_driver.c
c#include#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); // LED灯的驱动程序结构体struct led0_driver { struct cdev *cdev; }; // LED灯的驱动程序函数指针static int (*led0_ops)(struct file *, void *); // LED灯的初始化函数static int __init led0_init(void) { // 初始化LED灯的驱动程序结构体 struct led0_driver *led = kmalloc(sizeof(struct led0_driver), GFP_KERNEL); if (!led) { printk(KERN_ERR "Failed to allocate memory for led driver "); return -1; } // 注册LED灯的设备文件 cdev_init(&led->cdev, &led_fops); led->cdev->owner = THIS_MODULE; // 添加LED灯的设备文件到系统中 if (cdev_add(led->cdev, LED_MAJOR,0) < 0) { printk(KERN_ERR "Failed to add device file "); return -1; } // 初始化LED灯的驱动程序函数指针 led0_ops = &led0_read; return0; } // LED灯的读取函数static ssize_t led0_read(struct file *file, char __user *buf) { //读取LED灯的状态 int state =1; //代表LED灯是打开的 // 将LED灯的状态写入缓冲区 if (copy_to_user(buf, &state, sizeof(state))) { printk(KERN_ERR "Failed to copy data to user space "); return -1; } return sizeof(state); } module_init(led0_init);
#### led1_driver.c
c#include#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); // LED灯的驱动程序结构体struct led1_driver { struct cdev *cdev; }; // LED灯的驱动程序函数指针static int (*led1_ops)(struct file *, void *); // LED灯的初始化函数static int __init led1_init(void) { // 初始化LED灯的驱动程序结构体 struct led1_driver *led = kmalloc(sizeof(struct led1_driver), GFP_KERNEL); if (!led) { printk(KERN_ERR "Failed to allocate memory for led driver "); return -1; } // 注册LED灯的设备文件 cdev_init(&led->cdev, &led_fops); led->cdev->owner = THIS_MODULE; // 添加LED灯的设备文件到系统中 if (cdev_add(led->cdev, LED_MAJOR,0) < 0) { printk(KERN_ERR "Failed to add device file "); return -1; } // 初始化LED灯的驱动程序函数指针 led1_ops = &led1_read; return0; } // LED灯的读取函数static ssize_t led1_read(struct file *file, char __user *buf) { //读取LED灯的状态 int state =2; //代表LED灯是打开的 // 将LED灯的状态写入缓冲区 if (copy_to_user(buf, &state, sizeof(state))) { printk(KERN_ERR "Failed to copy data to user space "); return -1; } return sizeof(state); } module_init(led1_init);
#### led2_driver.c
c#include#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); // LED灯的驱动程序结构体struct led2_driver { struct cdev *cdev; }; // LED灯的驱动程序函数指针static int (*led2_ops)(struct file *, void *); // LED灯的初始化函数static int __init led2_init(void) { // 初始化LED灯的驱动程序结构体 struct led2_driver *led = kmalloc(sizeof(struct led2_driver), GFP_KERNEL); if (!led) { printk(KERN_ERR "Failed to allocate memory for led driver "); return -1; } // 注册LED灯的设备文件 cdev_init(&led->cdev, &led_fops); led->cdev->owner = THIS_MODULE; // 添加LED灯的设备文件到系统中 if (cdev_add(led->cdev, LED_MAJOR,0) < 0) { printk(KERN_ERR "Failed to add device file "); return -1; } // 初始化LED灯的驱动程序函数指针 led2_ops = &led2_read; return0; } // LED灯的读取函数static ssize_t led2_read(struct file *file, char __user *buf) { //读取LED灯的状态 int state =3; //代表LED灯是打开的 // 将LED灯的状态写入缓冲区 if (copy_to_user(buf, &state, sizeof(state))) { printk(KERN_ERR "Failed to copy data to user space "); return -1; } return sizeof(state); } module_init(led2_init);
### 设备文件操作当用户空间程序打开设备文件时,内核会调用对应的读取函数(如 `led0_read`、`led1_read` 和 `led2_read`)。这些函数负责将LED灯的状态写入缓冲区。
例如,如果用户空间程序使用以下代码打开设备文件:
cint main() { int fd = open("/dev/led0", O_RDONLY); if (fd < 0) { perror("open"); return -1; } char buf[4]; ssize_t len = read(fd, buf, sizeof(buf)); if (len < 0) { perror("read"); close(fd); return -1; } printf("%