字符设备驱动框架

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux中设备分类:

按照对设备的访问方式可分为以下三类:

1.字符设备(char device)

(1)例如:键盘、鼠标、串口、帧缓存等;

(2)通过/dev/下的设备节点访问;以字节为单位访问;

(3)一般只支持顺序访问;(特例:帧缓存framebuffer)

(4)无缓冲。

2.块设备(block device)

(1)例如:磁盘、光驱、flash等;

(2)以固定大小为单位访问:磁盘以扇区(512B)为单位;flash以页为单位。

(3)支持随机访问;

(4)有缓冲(减少磁盘IO,提高效率)。

3.网络设备(network device)

(1)无设备文件(节点);

(2)应用层通过socket接口访问网络设备(报文发送和接收的媒介)。

设备驱动在内核中的结构:

1.VFS虚拟文件系统作用:向应用层提供一致的文件访问接口,正是由于VFS

的存在,才可以将设备以文件的方式访问。

2.虚拟文件系统,存在于内存中,不在磁盘上,掉电丢失。例如:/proc、/sys、

/tmp。

设备号:

1.作用:唯一地标识一个设备;

2.类型:dev_t devno;即32位无符号整型;

3.组成:

(1)主设备号:用于区分不同类型(按功能划分)的设备;

(2)此设备号:用于区分相同类型的不同设备。

注意:相同类型的设备(主设备号相同)可以使用同一个驱动。

4.构建设备号:

int major = 250; int minor = 0;

(1)dev_t devno = (major << 20) | minor;不建议使用;

(2)利用宏来构建:dev_t devno = MKDEV (major, minor);

注意:我们可以通过文件$(srctree)/documentation/device.txt来查看内核对设备号的分配情况。

(1)该文本中的有对应设备文件的设备号是已经被申请过的,我们不可以重

复使用(申请);

(2)从中可以看出,我们在编写驱动程序时可以使用的主设备号范围为

240~254,为了方便记忆,通常使用250作为主设备号。

字符设备驱动框架:

驱动:作用,为应用层提供访问设备的接口(对设备发的各种操作)。

一、申请设备号

1.构建设备号:dev_t devno = MKDEV (major, minor);

2.申请设备号:

(1)动态申请:alloc_chrdev_region;

(2)静态申请: register_chrdev_region。

(3)静态申请设备号的优缺点:

优点:可以提前创建设备文件;

缺点:有可能会发成冲突,导致申请失败。

(4)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成员外,其他成员均是对文件进行相关操作的函数指针。

1.对设备的大多数操作函数都有参数struct file *filp;

2.在起始阶段我们可以先定义一个空的操作集合:

struct file_operations { .owner = THIS_MODULE };

注意:

(1)可以看出宏THIS_MODULE代表结构体struct module的起始地址;

(2)我们可以通过“. = <……>,”语法来给结构

体指定成员赋值。

三、注册字符设备:

1.通过结构体struct cdev将设备号devno和操作集合file_operations

关联起来;

2.并将cdev结构体加入到内核维护的cdev链表中。(计算机系统支持很多

字符设备,内核会维护一个cdev链表,这样我们就可以通过设备号找到

对应的操作集合了)

3.cdev结构体的定义如下:

4.我们通过调用内核函数cdev_init和cdev_add来完成字符设备的注册。

相关文档
最新文档