• 等待队列 阻塞非阻塞


    阻塞
    设备驱动不阻塞,用户想获取设备资源只能不停的查询,这无谓的消耗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);
  • 相关阅读:
    第五周作业
    第四周作业
    第三周作业
    第二周作业
    第一周作业
    FileZilla连接centos7失败处理(SSH)
    单例设计模式
    JQuery中的$符号的作用----网摘
    浅谈关于“中文编程”是否会成为中国程序员的一颗“银弹”
    第8周作业 邱鹏 2013551628
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709674.html
Copyright © 2020-2023  润新知