博客
关于我
设备驱动之阻塞
阅读量:339 次
发布时间:2019-03-04

本文共 3492 字,大约阅读时间需要 11 分钟。

一:阻塞与非阻塞概念:

1.1

    阻塞操作是指执行设备操作时,如果不能获取资源,则挂起进程直到满足可操作的条件后再进行操作    被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足,而非阻塞操作的    进程在不能进设备操作的时候,并不挂起,它要么放弃,要么不停的查询,直到可以进行操作为止,

1.2

    在阻塞访问时候,不能获取资源的进程将会进入休眠,将CPU资源让给其他进程。因为阻塞的进程会进入    休眠状态,所以必须保证有一个地方可以唤醒休眠的进程,否则,进程就真的寿正终寝了,唤醒进程的地    方最大可能发生在中断里面,因为在硬件资源获得的同时往往伴随这一个中断。非阻塞的进程不断的尝试    知道了可以进行I/O

1.3

    应用程序可以选择是以 阻塞 或者 非阻塞的方式访问:    阻塞的访问方式: fd = open("/dev/xxx", O_RDWD);    非阻塞的当时访问 : fd = open("/dev/xxx", O_RDWD | O_NONBLOCK);

1.4

    问题:为什么要引入阻塞与非阻塞操作    答案:驱动程序通常需要提供这样的能力:当应用程序进行 read() write() 等系统调用的时候,若        设备资源不能获取,正常情况下read() write()等操作会立即返回,需要重新访问,但是用户        要求上层只进行一次设备的读写操作,驱动内部的xxx_read xxx_write 等待资源可获取,完成        上层read() write();此时便有了阻塞访问,以及对应的非阻塞访问。

二:关于 阻塞-等待队列 的操作

    Linux设备驱动中,可以使用的等待队列(Qait Queue)来实现阻塞进程的唤醒,阻塞的进程可以使用等待队列(Wait_Queue)来实现唤醒,等待队列很早就作为一个基本功能出现在Linux内核里面了,等待队列以 队列 为基础数据结构,与进程调度机制紧密结合,可以用来同步对系统资源的访问。

2.1 等待队列操作:

        1   wait_queue_head_t   my_head //定义等待队列头        2   init_waitqueue_head(&my_head) //初始化等待队列头            DECLARE_WAIT_QUEUE_HEAD(name) //初始化等待队列头 宏        3 DECLARE_WAITQUEUE(name,tsk) //定义等待队列元素        4   add_wait_queue(wait_queue_head_t *q,wait_queue_t *wait) //添加等待队列元素          remove_wait_queue(wait_queue_head_t *q,wait_queue_t *wait)//移除等待队列元素        5   wait_event(queue,condition)//等待事件             wait_event_interruptible(queue,condition) //          等待第一个参数作为等待队列头部的队列被唤醒,第二个参数condition必须被满足,他们的区别          是 wait_event_interruptible 可以被信号打断,前者不能;        6   wake_up(wait_queue_head_t *queue)//唤醒队列          wake_up_interruptible(wait_queue_head_t *queue)//唤醒队列          唤醒以 queue作为等待队列头部的队列中的所有进程,wake_up可有唤醒处于 TASK_INTERRUPTIBLE           和 TASK_UNINTERRUPTIBLE 的进程,而 wake_up_interruptible 只能唤醒处于TASK_INTERRUPTIBLE状态的          进程

2.2:例程:

         在设备驱动中使用等待队列模板:         static ssize_t mac_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)        {        0 //定义等待队列头部        1 //定义等待队列元素            DECLARE_WAITQUEUE(wait,current);            mutex_lock(&dev->mutex);        2 //添加到等待队列            add_wait_queue(&dev->r_wait, &wait);            //等待 缓冲区可写            while(dev->current_len == 0){                    //如果是非阻塞访问                    if(filp->f_flags & O_NONBLOCK){                        return -EAGAIN;                        }                    //阻塞访问        3           //进行进程状态切换,设置当前进程状态为 浅睡眠,并没有真正睡眠                    __set_current_state(TASK_INTERRUPTIBLE);                    mutex_unlock(&dev->mutex);        4           //调度当前读进程出去 其他进程执行 此时读进程进入睡眠状态                    schedule();                     //由于当前读进程切换出去的时候是 TASK_INTERRUPTIBLE 状态,可以被信号唤醒                    //判断是否是信号唤醒进程,如果是 将读进程移除等待队列,并设置进程状态已运行        5           if(signal_pending(current))                        {                            remove_wait_queue(&dev->r_wait, &wait);//从附属的等待队列移除                            set_current_state(TASK_RUNNING);                            return - ERESTARTSYS;                        }                        mutex_lock(&dev->mutex);                }            wake_up_interruptible(&dev->w_wait);//唤醒可能阻塞的写进程           return 0;        }         注意 :因为进程调度出去的时候 的进程状态是  TASK_INTERRUPTIBLE ,即浅度睡眠,所以           唤醒他的可能是信号,因此我们首先通过 signal_pending(current)了解是不是信号           唤醒           无论是 读函数 还是写函数,在执行 schedule() 把自己切换出去之前,都要主动释放互斥体           因为如果读进程阻塞,说明是 fifo 空,必须依赖写进程往 FIFO 里面写东西来唤醒读进程,但是           写进程为了写 FIFO 也必须要拿到这个互斥锁来访问这个FIFO临界资源,如果读进程在把自己调度           出去之前没有释放这个互斥体,那么写进程就无法获得互斥体,也就是无法访问FIFO临界资源,导致           读写进程的锁死。

转载地址:http://home.baihongyu.com/

你可能感兴趣的文章
BUUCTF 新年快乐 内涵的软件 Java逆向解密 刮开有奖
查看>>
angr学习笔记(7)(malloc地址单元符号化)
查看>>
angr学习笔记(9)(添加约束)
查看>>
angr学习笔记(13)(static_binary)
查看>>
windows环境利用start命令实现微信多开
查看>>
「CF149D」括号涂色 区间DP好题
查看>>
树状数组 模板总结
查看>>
「NOI2015」程序自动分析 并查集题解
查看>>
[JSOI2008]Blue Mary的战役地图 Hash题解
查看>>
Ubuntu修改终端上显示的用户名和主机名(详细步骤)
查看>>
教你写一手漂亮的伪代码(详细规则&简单实例)
查看>>
MySQL数据备份实践和整理
查看>>
结构型设计在工作中的一些经验总结
查看>>
如何提升员工体验 助力企业业务增长?这个棘手的问题终于被解决了!
查看>>
腾讯物联网操作系统正式开源,最小体积仅1.8 KB
查看>>
不懂数据库的码农不是好程序员!
查看>>
全球首个!阿里云开源批流一体机器学习平台Alink……
查看>>
红点中国、红杉中国联合领投,WakeData惟客数据完成1000万美元B轮融资
查看>>
OpenStack发布Ussuri版本 实现智能开源基础设施的自动化
查看>>
整理了一份 Docker系统知识,从安装到熟练操作看这篇就够了 | 原力计划
查看>>