当前位置:文档之家› 字符驱动框架

字符驱动框架

字符驱动框架1.1.1 字符驱动框架接下来将前面所讲述的编写驱动的知识融合起来,给出一个完整的字符驱动程序的框架,一个典型的字符驱动框架略缩图如图0.1所示。

相关头文件相关变量和宏定义#include <linux/init.h> #include <linux/module.h>...static int char_cdev_open(struct inode *inode, struct file *file ){}open 方法static int char_cdev_release(struct inode *inode, struct file *file ){}release 方法static ssize_t char_cdev_read(struct file *file, char *buf,size_t count, loff_t *f_pos){}read 方法static ssize_t char_cdev_write(struct file *file, const char *buf, size_t count, loff_t *f_pos){}write 方法static int char_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){}ioctl 方法struct file_operations char_cdev_fops = { .owner = THIS_MODULE, .read = char_cdev_read, .write = char_cdev_write,.open = char_cdev_open, .release = char_cdev_release, .ioctl = char_cdev_ioctl };fops 定义static int __init char_cdev_init(void){}module_init(char_cdev_init);static void __exit char_cdev_exit(void){}module_exit(char_cdev_exit);MODULE_LICENSE("GPL");模块初始化代码模块退出代码协议声明模块描述图0.1 char_cdev 字符驱动框架略缩图从略缩图来看,字符驱动框架很简单,与前面一节程序代码相比,只增加了fops的定义以及char_cdev_xxx各方法的实现(尽管差不多是空函数)。

一般的字符驱动都可以套用这个框架,增加设备的实质性操作代码即可。

字符驱动框架完整代码如程序清单0.1所示。

程序清单0.1字符驱动程序框架1 #include <linux/init.h>2 #include <linux/module.h>3 #include <linux/fs.h>4 #include <linux/cdev.h>5 #include <linux/device.h>67 static int major = 232; /* 静态设备号方式的默认值*/8 static int minor = 0; /* 静态设备号方式的默认值*/9 module_param(major, int, S_IRUGO);10 module_param(minor, int, S_IRUGO);1112 struct cdev *char_cdev; /* cdev数据结构*/13 static dev_t devno; /* 设备编号*/14 static struct class *char_cdev_class;1516 #define DEVICE_NAME "char_cdev"1718 static int char_cdev_open(struct inode *inode, struct file *file )19 {20 try_module_get(THIS_MODULE);21 printk(KERN_INFO DEVICE_NAME " opened!\n");22 return 0;23 }2425 static int char_cdev_release(struct inode *inode, struct file *file )26 {27 printk(KERN_INFO DEVICE_NAME " closed!\n");28 module_put(THIS_MODULE);29 return 0;30 }3132 static ssize_t char_cdev_read(struct file *file, char *buf,size_t count, loff_t *f_pos)33 {34 printk(KERN_INFO DEVICE_NAME " read method!\n");35 return count;36 }3738 static ssize_t char_cdev_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)39 {40 printk(KERN_INFO DEVICE_NAME " write method!\n");41 return count;42 }4344 static int char_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)45 {46 printk(KERN_INFO DEVICE_NAME " ioctl method!\n");47 return 0;48 }4950 struct file_operations char_cdev_fops = {51 .owner = THIS_MODULE,52 .read = char_cdev_read,53 .write = char_cdev_write,54 .open = char_cdev_open,55 .release = char_cdev_release,56 .ioctl = char_cdev_ioctl57 };5859 static int __init char_cdev_init(void)60 {61 int ret;6263 if (major > 0) { /* 静态设备号*/64 devno = MKDEV(major, minor);65 ret = register_chrdev_region(devno, 1, "char_cdev");66 } else { /* 动态设备号*/67 ret = alloc_chrdev_region(&devno, minor, 1, "char_cdev"); /* 从系统获取主设备号*/68 major = MAJOR(devno);69 }70 if (ret < 0) {71 printk(KERN_ERR "cannot get major %d \n", major);72 return -1;73 }7475 char_cdev = cdev_alloc(); /* 分配char_cdev结构*/76 if (char_cdev != NULL) {77 cdev_init(char_cdev, &char_cdev_fops); /* 初始化char_cdev结构*/78 char_cdev->owner = THIS_MODULE;79 if (cdev_add(char_cdev, devno, 1) != 0) { /* 增加char_cdev到系统中*/80 printk(KERN_ERR "add cdev error!\n");81 goto error;82 }83 } else {84 printk(KERN_ERR "cdev_alloc error!\n");85 return -1;86 }8788 char_cdev_class = class_create(THIS_MODULE, "char_cdev_class");89 if (IS_ERR(char_cdev_class)) {90 printk(KERN_INFO "create class error\n");91 return -1;92 }9394 //device_create(char_cdev_class, NULL, devno, NULL, "char_cdev" "%d", MINOR(devno));95 device_create(char_cdev_class, NULL, devno, NULL, "char_cdev", NULL);96 return 0;9798 error:99 unregister_chrdev_region(devno, 1); /* 释放已经获得的设备号*/ 100 return ret;101 }102103 static void __exit char_cdev_exit(void)104 {105 cdev_del(char_cdev); /* 移除字符设备*/106 unregister_chrdev_region(devno, 1); /* 释放设备号*/107 device_destroy(char_cdev_class, devno);108 class_destroy(char_cdev_class);109 }110111 module_init(char_cdev_init);112 module_exit(char_cdev_exit);113114 MODULE_LICENSE("GPL");115 MODULE_AUTHOR("Chenxibing, linux@");对框架进行一些说明:⏹第(18)~(23)行是驱动open方法的实现代码,其中第(20)行的try_module_get()用于增加模块引用计数,设备每被打开1次,模块引用计数加1;⏹第(25)~(30)行市驱动release方法的实现代码,其中(28)行的module_put()用于递减模块引用计数,设备被关闭1次,模块引用计数减1;当引用计数为0时,模块可以被卸载;⏹第(32)~(36)行是驱动read方法的实现代码;⏹第(38)~(42)行是驱动write方法的实现代码;⏹第(44)~(48)行是驱动ioctl方法的实现代码;⏹第(50)~(57)行是驱动fops的定义;⏹在第(77)行通过cdev_init()将fops与设备相关联。

相关主题