linux字符设备驱动程序
来源:互联网 发布:收支软件下载 编辑:程序博客网 时间:2024/05/17 07:26
字符设备驱动程序:
主要有以下知识点:设备号、创建设备文件、重要数据结构、设备注册、设备操作。
设备号分主设备号和次设备号,可以进入/dev/ 中进行查看(ll)已经存在的设备文件。
主设备号是将 字符设备文件 和字符设备驱动 关联的关键。
主设备号用来反映设备类型,次设备号用来区分同类型的设备。
内核中 设备号 的字符类型是 dev_t ,其实是unsigned int 32位整数,其中高12位为主设备号,低20位为次设备号。
分解出主设备号的宏:MAJOR(dev_t dev);分解出次设备号的宏:MINOR(dev_t dev);结合成设备号的宏:MKDEV(ma,mi) //ma为主设备号,mi为次设备号
如何申请主设备号:静态申请,动态分配。
静态申请:
根据Documentation/devices.txt,确定一个没有使用的主设备号;
使用 register_chrdev_region 函数注册设备号。缺点:一旦驱动被广泛使用,这个随机选定的主设备号可能会导致设备号冲突,而使驱动程序无法注册。
int register_chrdev_region(dev_t from, unsigned count, const char *name);//申请使用从from开始的count个设备号(主设备号不变,次设备号增加),name设备名(体现在/proc/devices/)。
动态分配:
使用alloc_chrdev_region分配设备号。
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);//请求内核动态分配count个设备号,且次设备号从baseminor开始,dev为分配到的设备号,name为设备名(体现在/proc/devices)。
注销设备号:
void unregister_chrdev_region(dev_t from, unsigned count) ;//释放从from开始的count个设备号。
字符设备的注册或注销:
在lunux 2.6内核中,字符设备使用 struct cdev 来描述。字符设备的注册可分为如下三个步骤:1、分配cdev 2、初始化cdev 3、设备注册(添加cdev) 。
分配cdev:struct cdev *cdev_alloc(void);也可以直接定义变量。
初始化cdev:void cdev_init(struct cdev *cdev, const struct file_operations *fops) ;参数:cdev: 待初始化的cdev结构,fops: 设备对应的操作函数集。
添加cdev:int cdev_add(struct cdev *p, dev_t dev, unsigned count);参数:p: 待添加到内核的字符设备结构;dev: 设备号;count: 添加的设备个数。
通过以上的设备注册之后,insmod相应的模块之后,在/proc/devices会找到相应的设备以及其设备号(当然在rmmod之后就会取消)。
设备的注销:intcdev_del(structcdev *p);参数:p: 要注销的字符设备结构。
重要数据结构:
在linux字符设备驱动程序设计中,有三种非常重要的数据结构:struct file、struct inode、struct file_operations。
struct file:代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的 struct file,它由内核在打开文件时创建(即使是同样的文件被打开两次也会有两个struct file类型的变量被创建),在文件关闭后释放。
其中重要的成员loff_t f_pos /*文件读写位置,和lseek相似*/ 和 struct file_operations *f_op。
struct inode:用来记录文件的物理上的信息。因此,它和代表打开文件的file结构是不同的。一个文件可以对应多个file结构,但只有一个inode结构。重要成员:dev_t i_rdev:设备号。
struct file_operations:一个函数指针的集合,定义能在设备上进行的操作。结构中的成员指向驱动中的函数,这些函数实现一个特别的操作,对于不支持的操作保留为NULL。
设备操作,接下来必须得对struct file_operations *fops类型的变量进行初始化,其中函数指针指向的函数有:
int (*open)(structinode *, struct file *);在设备文件上的第一个操作,并不要求驱动程序一定要实现这个方法。如果该项为NULL,设备的打开操作还是可以成功。
void (*release)(struct inode *, struct file *);当设备文件被关闭时调用这个操作。与open相仿,release也可以没有。
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 file *, struct poll_table_struct *);对应select系统调用
int (*ioctl) (structinode *, struct file *,unsigned int, unsigned long);控制设备
int (*mmap)(struct file *, struct vm_area_struct *);将设备映射到进程虚拟地址空间中。
loff_t (*llseek) (struct file *,loff_t,int);修改文件的当前读写位置,并将新位置作为返回值。
Open方法:
Open方法是驱动程序用来为以后的操作完成初始化准备工作的。在大部分驱动程序中,open完成如下工作:初始化设备。标明次设备号。
Release方法:
Release方法的作用正好与open相反。这个设备方法有时也称为close,它应该:关闭设备。
读和写:
ssize_t xxx_read(struct file * filp, char __user *buff, size_t count,loff_t * offp);
ssize_t xxx_write(struct file *filp, char __user *buff, size_t count,loff_t *offp);
对于 2 个方法, filp是文件指针, count是请求传输的数据量。buff 参数指向数据缓存。最后, offp 指出文件当前的访问位置。
读和写方法都完成类似的工作:从设备中读取数据到用户空间;将数据传递给驱动程序。它们的原型也相当相似:
Read 和 Write 方法的 buff 参数是用户空间指针。因此, 它不能被内核代码直接引用,理由如下:用户空间指针在内核空间时可能根本是无效的---没有那个地址的映射。内核调用用户空间的指针必须要进行校验。
内核提供了专门的函数用于访问用户空间的指针,例如:
int copy_from_user(void *to, const void __user *from, int n)
int copy_to_user(void __user *to, const void *from, int n)
创建设备文件:
应用程序想要读取或者写入设备,必须要创建设备文件。
两种方法:1、用mknod;2、自动创建。
mknod用法:mknod filename(设备文件名) type(设备文件类型) major(主设备号) minor(次设备号),例:mknod serial0 c 100 0。
设备文件一般创建在 /dev/ 下,设备文件用于应用程序中访问目标设备而调用的文件,所以应用程序访问设备都是调用设备文件比如 fopen("/dev/memdev0","r+"); 。
- linux字符设备驱动程序
- Linux 字符设备驱动程序
- linux字符设备驱动程序
- Linux驱动程序-----字符设备
- Linux字符设备驱动程序
- Linux字符设备驱动程序
- Linux字符设备驱动程序
- linux设备驱动程序 字符设备驱动程序
- Linux设备驱动程序-字符设备驱动程序
- Linux字符设备驱动程序解析
- Linux字符设备驱动程序开发
- Linux 2.6 字符设备驱动程序
- Linux 2.6 字符设备驱动程序
- Linux 2.6 字符设备驱动程序
- Linux字符设备驱动程序开发
- Linux 2.6 字符设备驱动程序
- Linux 2.6 字符设备驱动程序
- Linux 2.6 字符设备驱动程序
- c# 数据库基础(将连接字符串写到配置文件中)
- java链接数据库代码
- 六款常用的linux C/C++ IDE
- ANSI和K&R两种函数定义风格
- OpenGL Transformation
- linux字符设备驱动程序
- 黑马程序员 【Head Firs Java (中文版)阅读笔记】 1章、2章、3章
- 内存_内存管理的不同阶段
- JavaScript 笔记
- 又一个lua与C++粘合层框架
- input 选择图片文件后显示图片文件
- 使用GPS如何在软件和操作层面上实现快速高精度的定位?
- 基础算法 排序
- 周鸿祎:互联网公司衰落的六大原因