linux 设备驱动程序 (3) —— 字符设备驱动程序

来源:互联网 发布:如何防止脱发 知乎 编辑:程序博客网 时间:2024/06/06 09:13
 一 scull的设计
scull 是一个操作内存区域的字符设备驱动程序

二 主设备号和次设备号
对字符设备的访问时通过文件系统内的设备名称进行的。
ls -l 在日期的数字为主设备和次设备号

主设备号标识着对应的驱动程序
现代linux内核允许多个驱动程序共享主设备号,但大多数一个主设备号对应一个驱动程序


次设备号由内核使用,用于正确确定设备文件所指的设备。依赖于驱动程序的编写方法
可以通过次设备号获得一个指向内核设备的直接指针,也可以当自设备本地数组索引

三 设备编号的内部表达
dev_t 用来保存设备编号,2.6中dev_t为32位,12用来主设备号,其余用于次设备号。
最好使用宏
定义在<linux/kdev_t.h>中
获得主次设备号
MAJOR(dev_t dev);
MINOR(dev_t dev);
获得dev_t
MKDEV(int major, int minor);

2.6可容纳大量的设备,先前版本限制于266个主设备和255个次设备

四 分配和释放设备编号
建立字符设备,需要获得一个或多个设备编号
<linux/fs.h>
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first 药费被的设备编号范围起始值,通常为0
count 所申请连续设备编号的个数
name 设备名称 会出现在/proc/devices和sysfs中
返回值,成功为0,失败为负

动态分配主设备号
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
dev 用于输出
firstminor 要被请求的第一个次设备号, 0
其他同上

释放设备编号
void unregister_chrdev_region(dev_t first, unsigned int count);

还需要告诉捏合拿来的编号用来做什么,用户空间访问上述编号前,驱动程序需要将编号和内部函数连接起来,内部函数用来实现设备的操作。

五 动态分配主设备号
一部分主设备号是静态分给了常见设备 清单: Document/devices.txt
最好使用alloc_chrdev_region
动态分配的缺点:主设备号不能保证始终一致
/proc/devices 中显示了设备号对应的驱动

六一些重要的数据结构
大部分驱动会涉及的三个重要内核数据结构
file_operations, file, inode

file_operations  <linux/fs.h>
用来将驱动程序操作链接到设备编号
每个打开的文件和一组函数指针
这个结构的每一个字段都必须指向驱动程序中实现特定操作的函数
对于不支持的操作,使用NULL,对于不同的操作有不同的行为
( __user字符串,只是一种文档,用来表明是一个用户空间地址, 用来寻找对用户空间地址的错误使用)

file <linux/fs.h>
代表一个打开的文件,它由内核在open市创建,并传递到所有在该文件上的操作函数,直到close,在所有实例都被关闭之后,内核会释放这个结构

inode
内核用该结构在内部表示文件。与file不同,file代表打开的,对于一个文件可能有多个file,但谭们都指向单个inode

dev_t i_rdev 表示设备文件的inode,该字段包含了设备编号
    iminor()
    imajor() 从i_rdev上获得设备编号最好使用以上两个函数,提高可移植性
struct cdev *i_dev 表示字符设备的内部结构,当inode指向字符设备文件时,该字段包含了该结构的指针

七字符设备的注册
内核内部使用struct cdev结构表示字符设备,内核调用设备之前,必须分配并注册一个或多个该结构
<linux/cdev.h>