linux驱动开发阻塞和非阻塞IO

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

linux 设备中的阻塞和非阻塞I/O

一、等待队列

在linux 驱动程序中,可以使用等待队列来实现阻塞进程的唤醒。等待队列是以队列为基础数据结构,与进程调度机制紧密结合,能够用于实现内核中的异步事件通知机制。等待队列可以用来同步对系统资源的访问,在内核中,信号量也是依赖于等待队列来实现的。

作用:所有的等待资源的任务都被放入到等待队列中。

二、实现

等待队列是一个队列数据结构所以,队列有等待队列头和等待队列项。

在使用的时候要先初始化以下,定义了几个队列,就初始化几次。

在内核中include/linux/wait.h 中定义如下

struct lock_class_key

在内核中定义为空的结构体

在kernel/wait.c 中__init_waitqueue_head 函数的实现

第一句话的意思是自旋锁的初始化。最后一句话的意思是初始化队列头。在include/linux/list.h 中有实现代码:

在内核中为了方便使用,有一个宏可以完成等待队列头的定义和初始化:

name 就是等待队列的名字,也是等待队列头的名字,tsk 一般是写如当前的任务(进程)current

(内核中的全局变量,代表当前任务)。

Condition 为满足的条件。

三、程序分析

在本程序中用到了简单睡眠和手动睡眠两种方法。本驱动程序中的缓冲区是一个循环的缓冲区,类似与循环队列。当rp == rw 时候说明缓冲区空,定rp 与rw 相差1

时候,说明缓冲区满。操作和循环队列类似。

程序的源代码如下:

1、头文件

驱动程序中所需要的头文件如下:

2、全局变量

本驱动程序用到的全局变量

3、设备结构体定义

设备结构体中定义了设备的资源,包括等待队列,对于设备来说也是一种资源,信号也是设备的资源。

4、open函数

open函数中对于一些只有open时才用到的资源进行初始化和分配,并不一定要在加载函数中分配。

5、close函数

6、read函数

本函数当中用到了简单睡眠机制。调用宏wait_event_interruptible

下面是数据的读入操作

其中min是内核中定义的宏,取得两者之间的一个最小值

7、write函数

进入之前,首先获得信号量,判断缓冲区是否可写。

8、手动睡眠实现

这个函数在本驱动程序中主要是获得当前缓冲区是否可以写,若是不可以写,则进入等待队列睡眠,而这个过程是利用手动睡眠来实现的。

注意:在执行完prepare_to_wait之后,要调用内核调度核心函数,实现进程切换,因为当前进程已经是可中断的等待态。

9、判断缓冲区是否满

10、file_operations结构体

11、初始化cdev

12、加载函数

13、卸载函数

释放资源的顺序和申请资源的顺序正好相反

相关文档
最新文档