等待队列 阻塞非阻塞

来源:互联网 发布:seo手机优化软件 编辑:程序博客网 时间:2024/05/21 07:08

阻塞
设备驱动不阻塞,用户想获取设备资源只能不停的查询,这无谓的消耗CPU资源。而阻塞访问,不能获取资源的进程将进入休眠,它将CPU资源“礼让”给其他进程
唤醒进程的地方最大可能发生在中断里面,因为硬件资源获得的同时往往伴随着一个中断

定义头

wait_queue_head_t queue;

初始化头

#define init_waitqueue_head(q)  

定义

#define DECLARE_WAITQUEUE(name, tsk)    

添加

extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

移除

extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

等待事件

#define wait_event(wq, condition)#define wait_event_timeout(wq, condition, timeout)#define wait_event_interruptible(wq, condition)#define wait_event_interruptible_timeout(wq, condition, timeout)

wq:等待队列
condition:必须满足,否则继续阻塞
interruptible:可以被信号打断
timeout:超时时间。不论condition是否满足,均返回

wait_event

#define wait_event(wq, condition)                   \do {                                    \    if (condition)   //条件满足立即返回                     \        break;                          \    __wait_event(wq, condition);    //添加等待队列,阻塞             \} while (0)#define __wait_event(wq, condition)                     \do {                                    \    DEFINE_WAIT(__wait);                        \                                    \    for (;;) {                          \        prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \        if (condition)                      \            break;                      \        schedule();     //放弃CPU             \    }                               \    finish_wait(&wq, &__wait);                  \} while (0)

唤醒

#define wake_up(x)#define wake_up_interruptible(x)

wake_up和wait_event或wait_event_timeout成对使用,wake_up_interruptible和wait_event_interruptible或wait_event_interruptible_timeout成对使用
wake_up可唤醒处于TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE的进程,wake_up_interruptible只能唤醒处于TASK_INTERRUPTIBLE的进程

在等待队列上睡眠

extern void sleep_on(wait_queue_head_t *q);extern long sleep_on_timeout(wait_queue_head_t *q,                      signed long timeout);extern void interruptible_sleep_on(wait_queue_head_t *q);extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,                       signed long timeout);

一般不用,而是直接进行状态切换

举例

if (mutex_lock_interruptible(&ir->buf_lock))    return -ERESTARTSYS;DECLARE_WAITQUEUE(wait, current);   //定义等待队列add_wait_queue(&ir->buf.wait_poll, &wait);  //添加等待队列set_current_state(TASK_INTERRUPTIBLE);  //改变进程状态while (written < n) {    if (lirc_buffer_empty(&ir->buf))     {        if (filep->f_flags & O_NONBLOCK) //非阻塞        {            ret = -EWOULDBLOCK;            break;        }        if (signal_pending(current)) //因信号唤醒        {            ret = -ERESTARTSYS;            break;        }        schedule(); //调度其他进程        set_current_state(TASK_INTERRUPTIBLE);    }     else     {        lirc_buffer_read(&ir->buf, buf);        ret = copy_to_user((void *)outbuf+written, buf,                            ir->buf.chunk_size);        written += ir->buf.chunk_size;    }}remove_wait_queue(&ir->buf.wait_poll, &wait);   //将等待队列移出等待队列头set_current_state(TASK_RUNNING);    //改变进程状态TASK_RUNNINGmutex_unlock(&ir->buf_lock);
原创粉丝点击