• Linux等待队列


    typedef struct wait_queue_entry wait_queue_entry_t;

    1.定义“等待队列头部”

    wait_queue_head_t my_queue;
    wait_queue_head_t是__wait_queue_head结构体的一个typedef。
    struct wait_queue_head {
    spinlock_t lock;
    struct list_head head;
    };

    2.初始化“等待队列头部”

    init_waitqueue_head(&my_queue);
    而下面的DECLARE_WAIT_QUEUE_HEAD()宏可以作为定义并初始化等待队列头部的“快捷方式”

    DECLARE_WAIT_QUEUE_HEAD (name)

    #define init_waitqueue_head(wq_head)
    do {
    static struct lock_class_key __key;

    __init_waitqueue_head((wq_head), #wq_head, &__key);
    } while (0)

    void __init_waitqueue_head(struct wait_queue_head *wq_head, const char *name, struct lock_class_key *key)
    {
    spin_lock_init(&wq_head->lock);
    lockdep_set_class_and_name(&wq_head->lock, key, name);
    INIT_LIST_HEAD(&wq_head->head);
    }

    3.定义等待队列元素

    DECLARE_WAITQUEUE(name, tsk)
    该宏用于定义并初始化一个名为name的等待队列元素。

    #define DECLARE_WAITQUEUE(name, tsk)
    struct wait_queue_entry name = __WAITQUEUE_INITIALIZER(name, tsk)

    #define __WAITQUEUE_INITIALIZER(name, tsk) {
    .private = tsk,
    .func = default_wake_function,
    .entry = { NULL, NULL } }

    struct wait_queue_entry {
    unsigned int flags;
    void *private;
    wait_queue_func_t func;
    struct list_head entry;
    };

    此宏函数相当于:
    struct wait_queue_entry name = {
    .private = tsk,
    .func = default_wake_function,
    .entry = { NULL, NULL } }

    4.添加/移除元素

    void add_wait_queue(wait_queue_head_t *q, wait_queue_entry *wait);
    void remove_wait_queue(wait_queue_head_t *q, wait_queue_entry *wait);
    add_wait_queue()用于将等待队列元素wait添加到等待队列头部q指向的双向链表中,而
    remove_wait_queue()用于将等待队列元素wait从由q头部指向的链表中移除。

    5.等待事件

    wait_event(queue, condition)
    wait_event_interruptible(queue, condition)
    wait_event_timeout(queue, condition, timeout)
    wait_event_interruptible_timeout(queue, condition, timeout)
    等待第1个参数queue作为等待队列头部的队列被唤醒,而且第2个参数condition必须满足,否则继续
    阻塞。wait_event()和wait_event_interruptible()的区别在于后者可以被信号打断,而前者不能。加上
    _timeout后的宏意味着阻塞等待的超时时间,以jiffy为单位,在第3个参数的timeout到达时,不论condition
    是否满足,均返回

    #define wait_event(wq_head, condition)                                          \
    do {                                                                            \
            might_sleep();                                                          \
            if (condition)                                                          \
                    break;                                                          \
            __wait_event(wq_head, condition);                                       \
    } while (0)
    
    #define __wait_event(wq_head, condition)                                        \
            (void)___wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, 0,     \
                                schedule())
    
    
    #define ___wait_event(wq_head, condition, state, exclusive, ret, cmd)           \
    ({                                                                              \
            __label__ __out;                                                        \
            struct wait_queue_entry __wq_entry;                                     \
            long __ret = ret;       /* explicit shadow */                           \
                                                                                    \
            init_wait_entry(&__wq_entry, exclusive ? WQ_FLAG_EXCLUSIVE : 0);        \
            for (;; ) {                                                              \
                    long __int = prepare_to_wait_event(&wq_head, &__wq_entry, state);\
                                                                                    \
                    if (condition)                                                  \
                            break;                                                  \
                                                                                    \
                    if (___wait_is_interruptible(state) && __int) {                 \
                            __ret = __int;                                          \
                            goto __out;                                             \
                    }                                                               \
                                                                                    \
                    cmd;                                                            \
            }                                                                       \
            finish_wait(&wq_head, &__wq_entry);                                     \
    __out:  __ret;                                                                  \
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    wait_event_interruptible(wq, condition) 休眠,直到 condition 为真;
    休眠期间是可被打断的,可以被信号打断

    wait_event(wq, condition) 休眠,直到 condition 为真;
    退出的唯一条件是 condition 为真,信号也不好使

    wait_event_interruptible_timeout
    (wq, condition, timeout) 休眠,直到 condition 为真或超时;
    休眠期间是可被打断的,可以被信号打断

    wait_event_timeout(wq, condition, timeout) 休眠,直到 condition 为真;
    退出的唯一条件是 condition 为真,信号也不好使

    6.唤醒队列

    #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
    #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL)
    #define wake_up_all(x) __wake_up(x, TASK_NORMAL, 0, NULL)
    #define wake_up_locked(x) __wake_up_locked((x), TASK_NORMAL, 1)
    #define wake_up_all_locked(x) __wake_up_locked((x), TASK_NORMAL, 0)

    wake_up         :只唤醒等待队列中第一个等待的线程.
    wake_up_nr       :唤醒等待队列中从队列头开始的nr个等待的线程.
    wake_up_all       :唤醒等待队列中所有等待的线程.

    #define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
    #define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)
    #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)
    #define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1)

    7.在等待队列上睡眠

    sleep_on(wait_queue_head_t *q );
    interruptible_sleep_on(wait_queue_head_t *q );
    sleep_on()函数的作用就是将目前进程的状态置成TASK_UNINTERRUPTIBLE,并定义一个等待队
    列元素,之后把它挂到等待队列头部q指向的双向链,sleep_on()函数应该与wake_up()成对使用,interruptible_sleep_on()应该与wake_up_interruptible()成对使用。

  • 相关阅读:
    Linux 修改文件(文件夹)的权限 chown 与 chmod
    leetcode(c++)-买卖股票的最佳时机 II
    LLM在电商推荐系统的探索与实践
    9.13作业
    Unity反编译:IL2CPP 打包输出的cpp文件和dll(程序集)位置、Mono打包输出的dll(程序集)位置
    vue3基础学习
    Python内置函数
    Go学习之路:流程控制语句:for、if、else、switch 和 defer(DAY 1)
    @ConditionalOnProperty注解和@ConfigurationProperties注解
    Python:每日一题之四平方和
  • 原文地址:https://blog.csdn.net/qq_42861208/article/details/126754790