字符设备驱动框架.docx
文本预览下载声明
Linux中设备分类:按照对设备的访问方式可分为以下三类:字符设备(char device)例如:键盘、鼠标、串口、帧缓存等;通过/dev/下的设备节点访问;以字节为单位访问;一般只支持顺序访问;(特例:帧缓存framebuffer)无缓冲。块设备(block device)例如:磁盘、光驱、flash等;以固定大小为单位访问:磁盘以扇区(512B)为单位;flash以页为单位。支持随机访问;有缓冲(减少磁盘IO,提高效率)。网络设备(network device)无设备文件(节点);应用层通过socket接口访问网络设备(报文发送和接收的媒介)。设备驱动在内核中的结构:VFS虚拟文件系统作用:向应用层提供一致的文件访问接口,正是由于VFS的存在,才可以将设备以文件的方式访问。虚拟文件系统,存在于内存中,不在磁盘上,掉电丢失。例如:/proc、/sys、/tmp。设备号:作用:唯一地标识一个设备;类型:dev_t devno;即32位无符号整型;组成:31 主设备号major 2019 次设备号minor 0主设备号:用于区分不同类型(按功能划分)的设备;此设备号:用于区分相同类型的不同设备。注意:相同类型的设备(主设备号相同)可以使用同一个驱动。构建设备号:int major = 250; int minor = 0;dev_t devno = (major 20) | minor;不建议使用;利用宏来构建:dev_t devno = MKDEV (major, minor);注意:我们可以通过文件$(srctree)/documentation/device.txt来查看内核对设备号的分配情况。该文本中的有对应设备文件的设备号是已经被申请过的,我们不可以重复使用(申请);从中可以看出,我们在编写驱动程序时可以使用的主设备号范围为240~254,为了方便记忆,通常使用250作为主设备号。字符设备驱动框架:驱动:作用,为应用层提供访问设备的接口(对设备发的各种操作)。申请设备号构建设备号:dev_t devno = MKDEV (major, minor);申请设备号:动态申请:alloc_chrdev_region;静态申请: register_chrdev_region。静态申请设备号的优缺点:优点:可以提前创建设备文件;缺点:有可能会发成冲突,导致申请失败。register_chrdev_region函数详解:注意:最后一个参数是设备名称。且在/proc/devices下会有关于当前系统已经注册成功的设备信息;申请设备号应在加载函数中实现;同时,在卸载函数中我们也要调用unregister_chrdev_region来释放设备号。实现操作集合struct file_operations {……}struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*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 fiel *, poll_table *);int (*fasync) (int, struct file *, int);long (*unlock_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*release) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*lock) (struct file *, int, struct file_lock *);……};除owner成员外,其他成员均是对文件进行相关操作的函数指针。对设备的大多数操作函数都有参数struct file *filp;在起始阶段我们可以先定义一个空的操作集合:struct file_operations { .owner = THIS_MODULE };注意:可以看出宏THIS_MODULE代表结构体struct module的起始地址;我们可以通过“.
显示全部