你了解过Linux字符设备驱动框架?.doc
《你了解过Linux字符设备驱动框架?.doc》由会员分享,可在线阅读,更多相关《你了解过Linux字符设备驱动框架?.doc(6页珍藏版)》请在三一文库上搜索。
1、你了解过Linux字符设备驱动框架?字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行ls -l /dev的时候,就能看到大量的设备文件,c就是字符设备,b就是块设备,网络设备没有对应的设备文件。编写一个外部模块的字符设备驱动,除了要实现编写一个模块所需要的代码之外,还需要编写作为一个字符设备的代码。驱动模型Linux一切皆文件,那么作为一个设备文件,它的操作方法接口封装在struct file_operations,当我们写一个驱动的时候,一定要实现相应的
2、接口,这样才能使这个驱动可用,Linux的内核中大量使用注册+回调机制进行驱动程序的编写,所谓注册回调,简单的理解,就是当我们open一个设备文件的时候,其实是通过VFS找到相应的inode,并执行此前创建这个设备文件时注册在inode中的open函数,其他函数也是如此,所以,为了让我们写的驱动能够正常的被应用程序操作,首先要做的就是实现相应的方法,然后再创建相应的设备文件。#include /for struct cdev#include /for struct file#include /for copy_to_user#include /for error numberstaTIc in
3、t ma = 0;staTIc int mi = 0;const int count = 3;/* 准备操作方法集 */* struct file_operaTIons struct module *owner; /THIS_MODULE /读设备 ssize_t (*read) (struct file *, char _user *, size_t, loff_t *); /写设备 ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *); /映射内核空间到用户空间 int (*mmap) (struct
4、file *, struct vm_area_struct *); /读写设备参数、读设备状态、控制设备 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); /打开设备 int (*open) (struct inode *, struct file *); /关闭设备 int (*release) (struct inode *, struct file *); /刷新设备 int (*flush) (struct file *, fl_owner_t id); /文件定位 loff_t (*llseek)
5、 (struct file *, loff_t, int); /异步通知 int (*fasync) (int, struct file *, int); /POLL机制 unsigned int (*poll) (struct file *, struct poll_table_struct *); 。;*/ssize_t myread(struct file *filep, char _user * user_buf, size_t size, loff_t* offset) return 0;struct file fops = .owner = THIS_MODULE, .read =
6、 myread, .;/* 字符设备对象类型 struct cdev struct kobject kobj; struct module *owner; /模块所有者(THIS_MODULE),用于模块计数 const struct file_operaTIons *ops; /操作方法集(分工:打开、关闭、读/写、.) struct list_head list; dev_t dev; /设备号(第一个) unsigned int count; /设备数量;*/static int _init chrdev_init(void) . /* 构造cdev设备对象 */ struct cdev
7、 *cdev_alloc(void); /* 初始化cdev设备对象 */ void cdev_init(struct cdev*, const struct file_opeartions*); /* 申请设备号,静态or动态*/ /* 为字符设备静态申请第一个设备号 */ int register_chrdev_region(dev_t from, unsigned count, const char* name); /* 为字符设备动态申请第一个设备号 */ int alloc_chrdev_region(dev_t* dev, unsigned baseminor, unsigned
8、count, const char* name); ma = MAJOR(dev) /从dev_t数据中得到主设备号 mi = MINOR(dev) /从dev_t数据中得到次设备号 MKDEV(ma,1) /将主设备号和次设备号组合成设备号,多用于批量创建/删除设备文件 /* 注册字符设备对象cdev到内核 */ int cdev_add(struct cdev* , dev_t, unsigned); .static void _exit chrdev_exit(void) . /* cdev_del()、cdev_put()二选一 */ /* 从内核注销cdev设备对象 */ void
9、cdev_del(struct cdev* ); /* 从内核注销cdev设备对象 */ void cdev_put(stuct cdev *); /* 回收设备号 */ void unregister_chrdev_region(dev_t from, unsigned count); .罗嗦一句,如果使用静态申请设备号,那么最大的问题就是不要与已知的设备号相冲突,内核在文档Documentation/devices.txt中已经注明了哪些主设备号被使用了,从中可以看出,在2个主设备号中,我们能够使用的范围是240-255以及261-2-1的部分,这也可以解释为什么我们动态申请的时候,设备号
10、经常是250的原因。此外,通过这个文件,我们也可以看出,主设备号表征一类设备,但是字符/块设备本身就可以被分为好多类,所以内核给他们每一类都分配了主设备号。实现read,writeLinux下各个进程都有自己独立的进程空间,即使是将内核的数据映射到用户进程,该数据的PID也会自动转变为该用户进程的PID,由于这种机制的存在,我们不能直接将数据从内核空间和用户空间进行拷贝,而需要专门的拷贝数据函数/宏:long copy_from_user(void *to, const void _user * from, unsigned long n)long copy_to_user(void _use
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 了解 Linux 字符 设备 驱动 框架
链接地址:https://www.31doc.com/p-3381569.html