七、【misc】杂项驱动模型
一、杂项设备驱动设计步骤
1、定义一个杂项设备结构体
1 2 3 4 5 6 7 8 9 10 | struct miscdevice { int minor; //次设备号 const char *name; //设备名和设备文件名一致 const struct file_operations *fops; //文件操作集合 struct list_head list; struct device *parent; struct device *this_device; const char *nodename; umode_t mode; }; |
2、杂项设备的注册和注销
(1)注册
1 | int misc_register( struct miscdevice * misc) |
(2)注销
1 | int misc_deregister( struct miscdevice *misc) |
二、使用杂项设备模型写led流水灯驱动
1 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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/ioport.h> #include <linux/io.h> #include <linux/uaccess.h> #include <linux/types.h> #include <linux/gpio.h> #include <cfg_type.h> #include <linux/miscdevice.h> #define LED_ON _IOW('L',0,unsigned long) #define LED_OFF _IOW('L',1,unsigned long) struct led_gpio_t{ unsigned int gpio; char gpio_name[20]; }; static struct led_gpio_t led_gpioC[]= { {PAD_GPIO_C+17, "D8_GPIOC17" }, {PAD_GPIO_C+7, "D9_GPIOC7" }, {PAD_GPIO_C+8, "D10_GPIOC8" }, }; static long led_ioctl( struct file *flip, unsigned int cmd, unsigned long arg) { if (arg>10||arg<7) { return -EINVAL; } switch (cmd) { case LED_ON: gpio_set_value(led_gpioC[arg-8].gpio,0); break ; case LED_OFF: gpio_set_value(led_gpioC[arg-8].gpio,1); break ; default : return -ENOIOCTLCMD; } return 0; } struct file_operations led_misc_fops= { .unlocked_ioctl = led_ioctl, }; static struct miscdevice led_misc={ .minor = MISC_DYNAMIC_MINOR, //表示由系统分配次设备号 .name = "led_misc" , .fops = &led_misc_fops, }; static int __init led_init( void ) { int ret,i; printk(KERN_INFO "led_init\n" ); ret = misc_register(&led_misc); if (ret < 0) { printk(KERN_INFO "led misc register fail.\n" ); goto misc_register_err; } for (i=0;i<3;i++) { ret = gpio_request(led_gpioC[i].gpio, led_gpioC[i].gpio_name); if (ret < 0) { printk(KERN_INFO "gpio_request fail.\n" ); goto gpio_request_err; } } for (i=0;i<3;i++) { gpio_direction_output(led_gpioC[i].gpio, 1); } return 0; gpio_request_err: while (i--) { gpio_free(led_gpioC[i].gpio); } misc_register_err: return 0; } static void __exit led_exit( void ) { int i; printk(KERN_INFO "xxxx__exit\n" ); for (i=0;i<3;i++) { gpio_free(led_gpioC[i].gpio); } misc_deregister(&led_misc); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE( "GPL" ); |
main.c
1 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 | #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <sys/ioctl.h> #define LED_ON _IOW('L',0,unsigned long) #define LED_OFF _IOW('L',1,unsigned long) int main() { int fd,ret; char buff[2]={0}; fd = open( "/dev/led_misc" ,O_RDWR); if (fd<0) { perror ( "open led_misc error!" ); } while (1) { ioctl(fd,LED_ON,8); sleep(1); ioctl(fd,LED_OFF,8); ioctl(fd,LED_ON,9); sleep(1); ioctl(fd,LED_OFF,9); ioctl(fd,LED_ON,10); sleep(1); ioctl(fd,LED_OFF,10); } close(fd); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)