10、驱动中的阻塞与非阻塞IO

    阻塞,就是在获取资源的时候,不能获取到,那么就会将当前的进程挂起(睡眠,也就是将当前进程从调度器拿走了,不会调度当前进程),直到满足条件为止再进行操作。相反,非阻塞,就是即使不能获取到资源,非阻塞的进程是,要么是直接放弃,要么就不停地的进行查询,直到满足为止。

 

    当上层 read 或者 write 的时候,希望是阻塞地去获取资源时候,那么底层的驱动,就应该去以阻塞的方式去实现;而当是希望以非阻塞的方式的时候,当不慢满足的时候,就立即返回,且应用层收到 –EAGAIN 的返回值。

 

1、驱动中的阻塞

   底层驱动的阻塞操作,是借助了 等待队列的方式进行实现的,定义一个等待队列头,本质上是一个双向链表,队列的后续挂接了不同的节点,这些节点就是等待的任务,当在程序的某一个位置唤醒了等待队列头的时候,那么挂接在等待队列头的双向链表的任务节点,都会被唤醒。

 

1.1、API

(1)定义等待队列头

wait_queue_head_t myqueue; 

(2)初始化队列头

init_waitqueue_head(&myqueue);

    其实可以通过定义和初始化一体的宏代码: DECLARE-WAITQUEUQ(name)    name. 就是定义以及被初始化的头部

(3)定义等待任务

    DECLARE_WAITQUEUE(name, tsk)

    定义了一个等待任务,name。而 tsk 是任务进程,一般是设置为 current,也就是设置为当前的进程。

(4)添加/删除队列

    void add_wait_queue(wait_queue_head_t *myqueue, wait_queue_t * wait);

    void remove_wait_queue(wait_queue_head_t *myqueue, wait_queue_t * wait)

    将等待队列(wait),添加到 以myqueue 作为头部的,双向链表中,

(5)等待事件

    wait_event(myqueue, condition)

    将以 myqueue 的队列,全部进行阻塞,等待 condition 为真,不能被打断

    wait_event_interruptible(wq, condition)    ,是先等待的同时,可以被打断

(6)唤醒队列

wake_up(wait_queue_head_t *myqueue)

    唤醒等待队列头,会将队列中的所有进程都进行唤醒。

 

2、驱动的非阻塞

     驱动中的非阻塞实现,可以通过 struct file 中的 f_flags 标志进行判断,当 f_flags & O_NONBLOCK (因为上次应用的标志位的设置的时候,不仅仅是非阻塞,也有其他的,所以用 与,而不是等号)不等于零的,在资源不能获取的时候,立刻进行返回。还有一种是借助了 select 或者 poll 实习。

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

nfd : 是检测文件描述符中最大的 加一,

fd_set  : 是检测文件的文件集,可见,可以按照读、写、异常,分开进行检测

timeout :阻塞时间,

    select 会对指定的文件,进行实时检测,当检测到文件状态的变动,立马返回;没有检测到的时候,就直接进行阻塞,,但是阻塞不是一直进行下去的,阻塞的时间是通过 timeout 指定的时间。超过时间,即使没有检测到,也进行返回

2.1、文件集的设置

void FD_CLR(int fd, fd_set *set);   // 清空文件集
int FD_ISSET(int fd, fd_set *set);  // 检测文件,是否以及被置为到文件集
void FD_SET(int fd, fd_set *set);  // 将文件描述符,置为到文件集
void FD_ZERO(fd_set *set);   // 清空

 

2.2、底层poll

    当上层调用了select 或者 poll 、epoll 的时候,底层的 poll  被调用,

unsigned int (*poll) (struct file *, struct poll_table_struct *);

第一个参数,是被打开文件,相关的参数;第二个参数,是被轮询设备的表格。poll 函数里面,当返回的时候,需要返回以下:

POLLIN : 表示设备可读,参考是应用层,

POLLOUT : 表示设备可写,

POLLERR : 错误

POLLRDNORM :必须被设置,

一般是:

unsigned int (*poll) (struct file *, struct poll_table_struct *)

{

        if (XXXXX)

           mask |= POLLIN |  POLLRDNORM ;

        else

             mask |= POLLOUT |  POLLRDNORM ;

}

时间: 2024-10-25 23:14:59

10、驱动中的阻塞与非阻塞IO的相关文章

Linux设备驱动中的阻塞和非阻塞I/O

[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到条件满足. 2.非阻塞 非阻塞操作是指在进行设备操作是,若操作条件不满足并不会挂起,而是直接返回或重新查询(一直占用CPU资源)直到操作条件满足为止. 当用户空间的应用程序调用read(),write()等方法时,若设备的资源不能被获取,而用户又希望以阻塞的方式来访问设备,驱动程序应当在设备驱动层的

Linux设备驱动中的阻塞与非阻塞IO与并发控制

Linux设备驱动中的阻塞与非阻塞IO: 1.Linux设备驱动中的阻塞与非阻塞总结:http://m.blog.csdn.net/blog/dongteen/17264501 2.Linux设备驱动中的阻塞与非阻塞IO:http://m.blog.csdn.net/blog/dongteen/17264501 3.Linux设备驱动中的阻塞与非阻塞I/O实例:http://blog.csdn.net/wenhui_/article/details/6817659 linux内核中等待队列: 1

深入浅出~Linux设备驱动中的阻塞和非阻塞I/O

今天意外收到一个消息,真是惊呆我了,博客轩给我发了信息,说是俺的博客文章有特色可以出本书,,这简直让我受宠若惊,俺只是个大三的技术宅,写的博客也是自己所学的一些见解和在网上看到我一些博文以及帖子里综合起来写的,,总之这又给了额外的动力,让自己继续前进,,希望和大家能够分享一些自己的经验,,在最需要奋斗的年级以及在技术的领域踽踽独行的过程中有共同的伙伴继续前进~ 今天写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说就是对I/O操作的两种不同的方式,驱动程序可以灵活的

Linux设备驱动中的IO模型---阻塞和非阻塞IO【转】

在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程——网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: a -- 阻塞I/Ob -- 非阻塞I/Oc -- I/O复用(select和poll)d -- 信号驱动I/O(SIGIO)e -- 异步I/O(Posix.1的aio_系列函数) 下面我们先学习阻塞I/O.非阻塞I/O .I/O复用(select和poll),先学习一下基础概念 a -- 阻塞 

linux驱动编写之阻塞与非阻塞

一.概念 应用程序使用API接口,如open.read等来最终操作驱动,有两种结果--成功和失败.成功,很好处理,直接返回想要的结果:但是,失败,是继续等待,还是返回失败类型呢?  如果继续等待,将进程休眠,那么这类驱动设计就是阻塞式的:如果不等待,返回失败的类型(原因),那么这类驱动的设计就是非阻塞式的. 在应用程序打开驱动文件的时候,可以通过参数向驱动传递使用驱动的方式(阻塞或者非阻塞),通过flags这个参数来传递.当flags中包含"O_NONBLOCK",就是非阻塞,否则就是

《linux设备驱动开发详解》笔记——8阻塞与非阻塞IO

8.1 阻塞与非阻塞IO 8.1.0 概述 阻塞:访问设备时,若不能获取资源,则进程挂起,进入睡眠状态:也就是进入等待队列 非阻塞:不能获取资源时,不睡眠,要么退出.要么一直查询:直接退出且无资源时,返回-EAGAIN 阻塞进程的唤醒:必须有地方能够唤醒处于睡眠状态的阻塞进程,否则就真睡不醒了.一般是在中断中. 阻塞与非阻塞可以在open时设置,也可以通过fcntl和ioctl重新设置 8.1.1 等待队列 linux驱动中,可以用等待队列wait queue实现阻塞.等待队列与linux进程调

Hasen的linux设备驱动开发学习之旅--阻塞与非阻塞I/O

/** * Author:hasen * 参考 :<linux设备驱动开发详解> * 简介:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:阻塞与非阻塞I/O * Date:2014-11-05 */ 阻塞操作是指在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作.被 挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.而非阻塞操作的进程在不能 进行设备操作时,并不挂起,它或者放弃,或者不停地查询,直到条件满足以进行操作为止.

关于python中同步、异步,阻塞、非阻塞的理解

同步.异步,阻塞.非阻塞的理解 异步:某个事情需要10秒.而我只需要调用一个函数帮我做,我可以干 其他的事情.(比如调用celery) 同步:某个事情需要10秒完成,我等他完成之后再继续后面的工作. 举例:金拱门排队取餐 第一种方式(同步),下单拿号之后自己排队取餐. 第二种方式(异步),下单之后可以坐在一旁等待叫号,等待事件触发. 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务,等待当前函数返回. 阻塞调用和同步调用不同点: 对于同步调用来说,很

Java中的阻塞和非阻塞IO包各自的优劣思考

NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式. 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞 与非阻塞 .所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止.而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待 . 一种常用做法是:每建立一个Socket

IO中同步异步,阻塞与非阻塞 -- 原理篇

再补一篇高手写的理论分析,便于更深刻理解 转自:http://blog.csdn.net/historyasamirror/article/details/5778378 ============================================================= 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答