[精选]字符设备驱动程序

上传人:我**** 文档编号:177537336 上传时间:2021-03-29 格式:PPTX 页数:43 大小:1.52MB
返回 下载 相关 举报
[精选]字符设备驱动程序_第1页
第1页 / 共43页
[精选]字符设备驱动程序_第2页
第2页 / 共43页
[精选]字符设备驱动程序_第3页
第3页 / 共43页
[精选]字符设备驱动程序_第4页
第4页 / 共43页
[精选]字符设备驱动程序_第5页
第5页 / 共43页
点击查看更多>>
资源描述

《[精选]字符设备驱动程序》由会员分享,可在线阅读,更多相关《[精选]字符设备驱动程序(43页珍藏版)》请在金锄头文库上搜索。

1、Linux字符设备驱动程序,Linux驱动程序的分类,字符设备驱动:用于驱动能够像字节流(文件)一样被访问的设备。应用程序通常可以利用open、close、read、write等系统调用访问字符设备驱动。 块设备驱动:块设备和字符设备只在系统内核内部的管理上有所区别。应用程序对于字符设备的每一个I/O操作都会被内核直接传递给对应的驱动程序;而应用程序对于块设备的操作要经过虚拟文件系统(VFS)和缓冲区管理系统间接地传递给驱动程序处理。 网络设备驱动:应用程序必须利用套接字(socket)接口访问网络设备,网络设备驱动程序,字符设备驱动程序基本结构,字符设备开发的基本步骤 确定主设备号和次设备号

2、 实现字符驱动程序 实现file_operations结构体 构造字符设备结构体cdev 在模块加载函数中注册字符设备 在模块卸载函数中注销字符设备 创建设备文件节点,设备文件与设备号,为了体现“一切都是文件”的设计思想,linux将每个已安装的设备都表示为一个设备文件。 设备文件通常位于/dev子目录。 对于字符设备,应用程序可以利用open、close、read、write等系统调用访问其设备文件,这些I/O操作都被直接传递给该设备文件所对应的设备。 每个设备文件中都存储了该设备的“主设备号”和“次设备号”。 一般由同一个内核模块管理的多个设备占用同一个主设备号,具体设备用次设备号标识。

3、用mknod filename c major minor命令创建设备文件 用rm filename命令删除设备文件。注意删除设备文件并不会影响驱动模块,应用程序如何访问设备,fd1 = open(“/dev/ttyS1”, O_RDWR); / 阻塞 fd2 = open(“/dev/ttyS1”, O_RDWR | O_NONBLOCK); / 非阻塞 int read(int fd, const void *buf, size_t length); int write(int fd, const void *buf, size_t length); int lseek(int fd, o

4、ffset_t offset, int whence); int ioctl( int fd, int cmd, void *arg); int close(int fd,设备号的内部表达,设备编号的内部表达 dev_t类型(32位): 用来保存设备编号(包括主设备号(12位)和次设备号(20位) 从dev_t获得主设备号和次设备号: MAJOR(dev_t); MINOR(dev_t); 将主设备号和次设备号转换成dev_t类型: MKDEV(int major,int minor,主设备号与次设备号,分配主设备号 手工分配主设备号:找一个内核没有使用的主设备号来使用,include int

5、 register_chrdev_region( dev_t first, unsigned int count, char *name,要分配的设备编号范围的起始值,次设备号经常为0,所请求的连续设备编号的个数,和该编号范围关联的设备名称,主设备号与次设备号,动态分配主设备号,include int alloc_chrdev_resion(dev_t *dev,unsigned int firstminor, unsigned int count,char *name,输出的设备号,要使用的被请求的第一个次设备号,主设备号与次设备号,释放设备号,void unregister_chrdev_

6、region(dev_t first, unsigned int count,通常在模块的清除函数中调用,记录字符设备的结构体cdev,实现字符驱动程序 cdev 结构体,struct cdev struct kobject kobj; /* 内嵌的kobject 对象 */ struct module *owner; /*所属模块*/ struct file_operations *ops; /*文件操作结构体*/ struct list_head list; dev_t dev; /*设备号*/ unsigned int count;,cdev的kobj、 list 、 count字段不用

7、我们关系和维护(内核代劳),我们只需将其ops字段指向为我们自己的file operations结构,对cdev结构体的操作,操作cdev的函数,void cdev_init( struct cdev *, struc t file_operations *); struct cdev *cdev_alloc(void) ; int cdev_add(st ruct cdev *, dev_t, unsigned) ; void cdev_del(struct cdev *,用于初始化cdev的成员,并建立cdev和file_operations之间的连接,分别向系统删除一个cdev,完成字符

8、设备的注销,通常在模块的卸载函数中调用,分别向系统添加一个cdev,完成字符设备的注册,通常在模块加载函数中调用,函数用于动态申请一个cdev 内存,file_operations 结构体,file_operations 结构体 字符驱动和内核的接口: 在include/linux/fs.h定义 字符驱动只要实现一个file_operations结构体并注册到内核中,内核就有了操作此设备的能力,struct file_operations struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (

9、*read) (struct file *, char _user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*open) (struct inode *, st

10、ruct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); /,file_operations 结构体,file_operations的主要成员: struct module *owner: 指向模块自身 open:打开设备 release:关闭设备 read:从设备上读数据 write:向设备上写数据 ioctl:I/O控制函数 llseek:定位读写指针 mmap:映射设备空间到进程的地址空间,file operations的初始化,st

11、ruct file_operations my_fops = .owner = THIS_MODULE, .llseek = my_llseek, .read = my_read, .write = my_write, .ioctl = my_ioctl, .open = my_open, .release = my_release,file结构体,file结构代表一个打开的文件,它由内核在应用程序open时创建,并将该文件所对应的file operations记录在file结构中。 在应用程序调用close函数,内核会释放该数据结构,struct file struct file_opera

12、tions*f_op; unsigned int f_flags; fmode_tf_mode; loff_tf_pos; structdentry*f_dentry void*private_data;,file结构体,file 结构体 file结构: file_operations结构相关的一个结构体。 描述一个正在打开的设备文件。 成员: loff_t f_pos: 当前读/写位置 unsigned int f_flags 标识文件打开时,是否可读或可写 O_RDONLY O_NONBLOCK O_SYNC struct file_operations *f_op 文件相关的操作,指向所

13、实现的struct file_operations void *private_data: 私有数据指针。驱动程序可以将这个字段用于任何目的或者忽略这个字段,inode结构体,内核用inode结构在内部表示文件,用于存储文件访问权限、属主、组、大小、生产时间等VFS关心的信息。 其字段中我们只关心i_rdev(设备号),和i_cdev(和该文件所对应的cdev结构) 我们在创建设备文件时,内核会自动创建一个对应的inode结构体,并将其i_cdev字段指向对应的字符设备结构体cdev(事先已经在内核中注册过)。 Inode与file的区别:file表示打开的文件描述符,多个file结构,可以指

14、向单个inode结构,struct inode dev_t i_rdev; struct cdev *i_cdev; /,Inode结构体,Inode结构中的两个主要字段: dev_t i_rdev; 对表示设备文件的inode结构,该字段包含了真正的设备编号。 struct cdev *i_cdev; struct cdev是表示字符设备的内核的内部结构。 当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针 从一个inode中获得主设备号和次设备号,unsigned int iminor(struct inode *inode); unsigned int

15、imajor(struct inode *inode,字符设备驱动程序基本结构,注册设备 ,在模块或驱动初始化时调用 Linux-2.4 及之前 Linux-2.6,int register_chrdev(unsigned int major, const char *name, struct file_operations *fops,如何操作字符设备的接口,void cdev_init( struct cdev *, struc t file_operations *); int cdev_add(st ruct cdev *, dev_t, unsigned),字符设备驱动程序基本结构,

16、注销设备:在模块卸载时调用 Linux-2.4及之前 Linux-2.6,int unregister_chrdev(unsigned int major, const char *name,void cdev_del (struct cdev *,字符设备驱动程序基本结构,/设备驱动模块加载函数 static int _init xxx_init(void) . cdev_init( / /注册设备 .,字符设备驱动程序基本结构,*设备驱动模块卸载函数*/ static void _exit xxx_exit(void) unregister_chrdev_region(xxx_dev_no, 1); / /释放占用的设备号 cdev_del( / /注销设备 .,字符设备驱动程序基本结构,打开 模块使用计数加1 识别次设备号 硬件操作: 检查设备相关错误(诸如设备未就绪或类似的硬件问题); 如果设备是首次打开,则对其初始化; 如果有中断操作,申请中断处理程序,int open(struct inode *inode, struct file *filp),字符设备驱动程序基

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > PPT模板库 > 其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号