[arm驱动]linux等待队列阻塞中断IO的应用

一、概念:
   要休眠进程,必须有一个前提:有人能唤醒进程,而起这个人必须知道在哪儿能唤醒进程,这里,就引入了“等待队列”这个概念。
二、应用场景:
   等待队列用来实现进程的阻塞,等待队列可看作保存进程的容器,在阻塞进程时,将进程放入等待队列,当唤醒进程时,从等待等列中取出进程。进程进入休眠后必须有个地方能够唤醒休眠的进程;唤醒进程的地方最大可能是中断里面,应为硬件资源的获取的同时往往伴随着一个中断。所以在中断中常常使用等待队列来休眠进程,将cpu资源让给其他进程,中断发生时唤醒进程
三、中断休眠相关函数
   1、生成等待事件的函数

   a)函数wait_event_interruptible(queue,condition)函数

wait_event_interruptible(queue,condition) //当condition(一个布尔表达式)为真时,立即返回;
//否则让进程进入TASK_INTERRUPTIBLE的睡眠,并挂在名为queue所指定的等待队列上。

    b)内核代码
 

#define wait_event_interruptible(wq, condition)               
  ({                                   
      int __ret = 0;                           
      if (!(condition))                       
          __wait_event_interruptible(wq, condition, __ret);   
      __ret;                               
  })

   2、wake_up_interruptible(queue);//唤醒队列中的名为queue的队列
   a)内核源码

   

#define wake_up_interruptible(x)    __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
    void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
            int nr_exclusive, void *key)
    {
        unsigned long flags;
        spin_lock_irqsave(&q->lock, flags);
        __wake_up_common(q, mode, nr_exclusive, 0, key);
        spin_unlock_irqrestore(&q->lock, flags);
    }

   3、定义队列名为queue的两种方法
   a)静态定义方法: DECLARE_QUEUE_HEAD(name)(常用)
       内核代码
         

#define DECLARE_WAIT_QUEUE_HEAD(name) wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
           #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {               
               .lock        = __SPIN_LOCK_UNLOCKED(name.lock),       
               .task_list    = { &(name).task_list, &(name).task_list } }

   b)动态定义方法:

wait_queue_head_t  my_queue;
                  init_waitqueue_head(&my_queue);

       内核代码

init_waitqueue_head(&my_queue)的内核代码
void init_waitqueue_head(wait_queue_head_t *q)
{
spin_lock_init(&q->lock);
INIT_LIST_HEAD(&q->task_list);
}

三、等待队列代码使用参考模板


staticDECLARE_WAIT_QUEUE_HEAD(queue);
staticintflag =0;
staticirqreturn_t irq_handle(intirq, void*dev__id){
//printk("irq = %d\n", irq);
//..........其他代码.............
flag = 1;
wake_up_interruptible(&queue);
returnIRQ_RETVAL(IRQ_HANDLED);//warn:杩斿洖IRQ_HANDLED
}
ssize_t XXXXX_read(structfile *filp,char__user *buf,size_tcount,loff_t *pos)
{
//pirntk(KERN_DEBUG "process %i (%s) going to sleep\n",current->pid,current->comm);
wait_event_interruptible(queue,flag);//此时进程被加入等待队列,等待中断发生
flag=0;
//printk(KERN_DEBUG "awoken %i (%s) \n",current->pid,current->comm);
returncount;//这个count变量看自己需要更改
}


实例见[arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作 中的实例










本文出自 “lilin9105” 博客,请务必保留此出处http://7071976.blog.51cto.com/7061976/1392461

[arm驱动]linux等待队列阻塞中断IO的应用,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。