linux等待队列

等待队列在Linux内核中用于管理睡眠进程,当特定条件满足时由内核唤醒。它基于双向链表,每个等待队列头带有自旋锁保护。等待队列可通过DEFINE_WAIT或DECLARE_WAIT_QUEUE_HEAD定义,使用add_wait_queue()或add_wait_queue_exclusive()将进程加入队列,并通过sleep_on系列函数或wait_event进行等待操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

等待队列(wait_queue)表示一组睡眠的进程, 当某种条件为真的时候, 由内核来唤醒它们.

等待队列由双向链表来实现, 每一个等待队列都有一个等待队列头(wait_queue_head).

struct __wait_queue_head {
	spinlock_t lock;
	struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;

由于等待队列经常由中断处理和其他的内核函数来修改所以要对其数据进行保护所以此处使用了spin_lock.

wait_queue_t:

struct __wait_queue {
	unsigned int flags;
#define WQ_FLAG_EXCLUSIVE	0x01
	void *private;
	wait_queue_func_t func;
	struct list_head task_list;
};

通过DEFINE_WAIT或者DECLARE_WAIT_QUEUE_HEAD来定义一个等待队列

#define DEFINE_WAIT(name)						\
	wait_queue_t name = {						\
		.private	= current,				\
		.func		= autoremove_wake_function,		\
		.task_list	= LIST_HEAD_INIT((name).task_list),	\
	}

/* DECLARE_WAIT_QUEUE */
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \
    .lock        = __SPIN_LOCK_UNLOCKED(name.lock),        \
    .task_list    = { &(name).task_list, &(name).task_list } }

#define DECLARE_WAIT_QUEUE_HEAD(name) \
    wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name) 

DECLARE_WAIT_QUEUE_HEAD创建一个变量然后初始化自旋锁和task_list.

DEFINE_WAIT用cpu上正在运行的进程(current)和autoremove_wake_function初始化该wait_queue_t变量, autoremove_wake_function实际调用default_wake_function()来唤醒睡眠的进程, 然后从wait_queue删除指定元素

default_wake_function实际调用了try_to_wake_up函数.

int default_wake_function(wait_queue_t *curr, unsigned mode, int sync,
			  void *key)
{
	return try_to_wake_up(curr->private, mode, sync);
}

一旦定义了一个元素,就必须把他插入等待队列使用add_wait_queue()函数:
 

void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{
	unsigned long flags;

	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
	spin_lock_irqsave(&q->lock, flags);
	__add_wait_queue(q, wait);
	spin_unlock_irqrestore(&q->lock, flags);
}

该函数把一个非互斥进程插入等待队列中第一个位置,先将等待队列中的flags保证为非互斥进程:wait->flags&=~WQ_FLAG_EXCLUSIVE;然后获取一个自旋锁并且保存中断状态, 使用__add_wait_queue函数将该进程插入等待队列, 最后释放该锁, 恢复中断状态.

__add_wait_queue函数(插入等待队列中第一个位置):

static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
	list_add(&new->task_list, &head->task_list);
}

add_wait_queue_exclusive和add_wait_queue类似不过不同的是wait->flags |= WQ_FLAG_EXCLUSIVE, 并且互斥进程调用__add_wait_queue_tail将互斥进程插入等待队列的尾部.

如果要等待特定条件的进程可以调用如下列表的函数:

  1. sleep_on
  2. interruptible_sleep_on
  3. sleep_on_timeout
  4. prepare_to_wait(), prepare_to_wait_exclusive(), finish_wait()
  5. wait_event
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值