8、linux设备驱动--阻塞型输入输出

来源:互联网 发布:微信互动软件 编辑:程序博客网 时间:2024/05/02 09:05
 1.阻塞与非阻塞I/O

   阻塞操作:在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作。被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足                                                                      

   非阻塞操作:在不能进行设备操作时,并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止                                                                      

   阻塞能使效率高:如果设备驱动不阻塞,则用户想获取设备资源时只能不停地查询,这反而会无谓地耗费CPU资源;而阻塞访问时,不能获取资源的进程将进入休眠,它将CPU资源“礼让”给其他进程                                                                     

   因为阻塞的进程会进入休眠状态,因此,必须确保有一个地方能够唤醒休眠的进程,否则,进程就真的“寿终正寝”了。唤醒进程的地方最大可能发生在中断里面,因为硬件资源获得的同时往往伴随着一个中断 

 

2.等待队列  

  在LINUX驱动程序中,可以使用等待队列(wait queue)来实现阻塞进程的唤醒,等待队列可以看作保存进程的容器,在阻塞进程时,将进程放入等待队列,当唤醒进程时,从等待队列中取出进程

  LINUX2.6提供如下关于等待队列的操作:                                                    

  1.定义“等待队列头”                                                                         

      wait_queue_head_t my_queue;                                                            

  2.初始化“等待队列头”                                                                      

      init_waitqueue_head(&my_queue);

 定义并初始化“等待队列头”的快捷方式(综合1、2步):                                            

      DECLARE_WAIT_QUEUE_HEAD(my_queue);                                                       

  3.添加/移除等待队列

      add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

      remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);  

   add_wait_queue()用于将等待队列wait添加到等待队列q指向的等待队列链表中         

  4.等待事件

      wait_event(queue, condition);

      wait_event_interruptible(queue, condition);                              

      wait_event_timeout(queue, condition, timeout);

      wait_event_interruptible _timeout(queue, condition, timeout);

   等待第一个参数queue作为等待队列头的等待队列被唤醒,而且第2个参数condition(bool表达式)必须满足,否则继续阻塞。wait_event()和

wait_event_interruptible()的区别在于后者能被信号打断,而前者不能。加上timeout后的宏意味着阻塞等待的超时时间,以jiffy为单位,在第3个参数timeout到达时,不论condition是否满足,均返回

  5.唤醒队列

      void wake_up(wait_queue_head_t *queue);

      void wake_up_interruptible(wait_queue_head_t *queue);

   wake_up()从等待队列queue中唤醒状态为TASK_UNINTERRUPTIBLE和

TASK_INTERRUPTIBLE的进程,而wake_up_interruptible()只能唤醒处于

TASK_INTERRUPTIBLE的进程

  6.在等待队列上睡眠

      sleep_on(wait_queue_head_t *q);

      interruptible_sleep_on(wait_queue_head_t *q);

   sleep_on()函数的作用就是将目前进程的状态置成TASK_UNINTERRUPTIBLE,并定义一个等待队列,之后把它附属到等待队列头q,直到资源可获得,q引导的等待队列被唤醒