从源码角度来解读Linux等待队列机制,了解休眠与唤醒的运转原理
kernel/include/linux/wait.h
kernel/kernel/sched/wait.c
kernel/include/linux/sched.h
kernel/kernel/sched/core.c
一、概述
Linux内核的等待队列是非常重要的数据结构,在内核驱动中广为使用,它是以双循环链表为基础数据结构,与进程的休眠唤醒机制紧密相联,是实现异步事件通知、跨进程通信、同步资源访问等技术的底层技术支撑。
研究等待队列这个内核非常基础的数据结构,对于加深理解Linux非常有帮忙,等待队列有两种数据结构:等待队列头(wait_queue_head_t)和等待队列项(wait_queue_t),两者都有一个list_head类型task_list。双向链表通过task_list将 等待队列头和一系列等待队列项串起来,源码如下所示。
二、等待队列
2.1 struct wait_queue_head_t
struct __wait_queue_head {
spinlock_t lock; //用于互斥访问的自旋锁
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
可通过宏DECLARE_WAIT_QUEUE_HEAD(name)
来创建类型为wait_queue_head_t的等待队列头name。
#define DECLARE_WAIT_QUEUE_HEAD(name) \
struct wait_queue_head name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
.head = { &(name).head, &(name).head } }
2.2 struct wait_queue_t
struct __wait_queue {
unsigned int flags;
void *private; //指向等待队列的进程task_struct
wait_queue_func_t func; //唤醒函数
struct list_head task_list; //链表元素,将wait_queue_t挂到wait_queue_head_t
};
typedef struct __wait_queue wait_queue_t;
可通过宏DECLARE_WAITQUEUE(name, tsk)
来创建类型为wait_queue_t的等待队列项name,并将tsk赋值给成员变量private, default_wake_function赋值给成员变量func。
#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 } }
<