等待队列 阻塞非阻塞

阻塞
设备驱动不阻塞,用户想获取设备资源只能不停的查询,这无谓的消耗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_RUNNING
mutex_unlock(&ir->buf_lock);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值