美文网首页
等待队列

等待队列

作者: gbmaotai | 来源:发表于2018-09-04 14:37 被阅读0次

工作队列和等待队列的区别

1.work queue

是一种bottom half,中断处理的后半程,强调的是动态的概念,即work是重点,而queue是其次。

create_singlethread_workqueue
queue_work
2.wait queue

是一种「任务队列」,可以把一些进程放在上面睡眠等待某个事件,强调静态多一些,重点在queue上,即它就是一个queue,等待队列是一种实现阻塞和唤醒的内核机制.

睡眠是“自愿调度”,其实就是将当前进程的状态设置为 TASK_INTERRUPTIBLE 等状态,然后schedule() 让出CPU1,让调度器重新选择一个进程来执行。

TASK_INTERRUPTIBLE
schedule()

等待队列

其他进程为了能够唤醒休眠的进程,它必须知道休眠的进程在哪里,出于这样的原因,需要有一个称为等待队列的结构体。等待队列是一个存放着等待某个特定事件进程链表。

定义并初始化一个链表。以后就能够在这个链表添加需要等待的进程了。

等待队列由循环链表实现,其元素包括指向进程描述符的指针。每个等待队列都有一个等待队列头(wait queue head),等待队列头是一个类型为wait_queue_head_t的数据结构

 a、等待队列头
        struct __wait_queue_head {  
            spinlock_t lock;  
            struct list_head task_list;  
        };  
typedef struct __wait_queue_head wait_queue_head_t;     
        
b、等待队列
        struct __wait_queue {  
            unsigned int flags;  
            void *private;  
            wait_queue_func_t func;  
            struct list_head task_list;  
        };  
typedef struct __wait_queue wait_queue_t;
clipboard.png

等待队列的使用

1、定义初始化等待队列头以及将条件置成假(condition = 0)。

静态定义初始化

#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 }}  

动态定义初始化

wait_queue_head_t test_queue; //1、定义等待队列头

//初始化等待队列头,注意函数调用的位置
 init_waitqueue_head(&my_dev.test_queue);
//它必须在cdev添加函数”cdev_add”前。因为”cdev_add”执行成功就意味着设备可以被操作,设备被操作前当然需要把所有的事情都干完,包括等待队列的初始化。
2、在需要阻塞的地方调用wait_event()函数,使进程进入睡眠,将控制权释放给调度器。在wait_event()函数的后面需要将条件置成假(condition = 0)。
if(wait_event_interruptible(dev->test_queue, dev->cur_size > 0))
 return - ERESTARTSYS;

wait_event(queue, condition)
wait_event_interruptible(queue, condition)
wait_event_timeout(queue, condition, timeout)
wait_event_interruptible_timeout(queue, condition, timeout)
3、当条件满足时,在内核的另一处,先将条件置成真(condition = 1),然后调用wake_up()函数唤醒等待队列中的睡眠进程。
 wake_up_interruptible(&dev->test_queue);

你调用 wake_up 去唤醒一个使用 wait_event 等,进入休眠的进程,唤醒之后,它会判断 condition 是否为真,如果还是假的继续睡眠。

手动睡眠,没有condition

  1. DECLARE_WAITQUEUE(name, tsk) 创建一个等待队列:
    tsk一般为当前进行current. 这个宏定义并初始化一个名为name的等待队列.
  2. 将等待队列头 加入/移除 等待队列:
        void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
        void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
        void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
  1. 设置进程状态:
set_current_state(TASK_INTERRUPTIBLE) 等

4.进程调度:

        schedule() 或者 schedule_timeout()

进程状态

TASK_INTERRUPTIBLE 与 TASK_UNINTERRUPTIBLE 区别在于,

它的休眠是否会被信号打断,别的进程发来一个信号比如 kill ,TASK_INTERRUPTIBLE 就会醒来去处理。然而 TASK_UNINTERRUPTIBLE 不会。schedule(),进程调度,而schedule_timeout()进行调度之后,一定时间后自动唤醒

相关文章

  • Select & Epoll原理

    预备知识 等待队列 等待队列有一个等待队列头,其他加入这个等待队列的需要加在这个头上。 需要加入等待队列的话,可以...

  • AQS源码解析

    等待队列中线程出队列时机 总的来说,一个线程获取锁失败了,被放入等待队列,acquireQueued会把放入队列中...

  • 等待队列

    工作队列和等待队列的区别 1.work queue 是一种bottom half,中断处理的后半程,强调的是动态的...

  • 等待队列

    等待队列 表示一组睡眠的进程,当某一条件为真时,由内核唤醒他们 在 Linux 中, 一个等待队列由一个"等待队列...

  • 等待队列

    等待队列概念以及使用 一、概述等待队列在内核中有很多用途,尤其在中断处理、进程同步及定时。等待队列实现事件上的条件...

  • Day30

    AQS 同步等待队列 & 条件等待队列 ReentrantLock同步执行,类似synchronized可重入 s...

  • 5、阻塞队列(BlockingQueue)和同步队列(Synch

    队列:FIFO(先进先出)阻塞: 写入:如果队列满了,就必须阻塞等待 读取:如果队列为空,必须阻塞等待生产。160...

  • AbstractQueuedSynchronizer (AQS)

    双队列 在AQS中,存在两个队列 等待队列:用于挂起当前线程,等待某个条件满足后唤醒或是被中断。 同步队列:多线程...

  • Java 通过阻塞队列实现生产者消费者模式

    阻塞队列 Blocking Queue 当队列空时,获取元素的线程会等待 当队列满时,存储元素的线程会等待 提供的...

  • go channel

    senq:等待发送的goroutine队列 recvq:等待接收的goroutine队列 buf是指向底层的循环数...

网友评论

      本文标题:等待队列

      本文链接:https://www.haomeiwen.com/subject/vjbgwftx.html