回复
Linux内核睡眠机制
JoyboyCZ
发布于 2023-3-29 17:26
浏览
0收藏
这里事先推荐给大家一个Linux源码的阅读网站,真的很方便!![preempt.h - tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h - Linux source code (v6.2.8) - Bootlin]
进程通过睡眠机制释放处理器,使其能够处理其它进程。处理器睡眠的原因可能在于感知数据的可用性,或等待资源释放。
内核调度器管理要运行的任务列表,这被称作运行队列。睡眠进程不再被调度,因为已将它们从运行列表中移除。除非其状态改变(唤醒),负责睡眠进程将永远不会被执行。进程一旦进入等待状态,就可以释放处理器,一定要确保有条件或其它进程会唤醒它。Linux内核通过提供一组函数和数据结构来简化睡眠机制的实现。
等待队列
等待队列实际上用于处理被阻塞的I/O,以等待特定条件成立,并感知数据或资源可用性。为了理解其工作方式,来看一看它在include/linux/wait.h中的结构
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
void *private;
wait_queue_func_t func;
struct list_head task_list;
};
入睡的每一个进程都在list_head中排队并进入睡眠状态。
处理等待队列将会用到如下常用函数:
-
静态声明:
DECLARE_WAIT_QUEUE_HEAD(name)
-
动态声明:
struct wait_queue_head { spinlock_t lock; /* 采用了自旋锁,要考虑自旋时长,避免过度影响系统性能 */ struct list_head head; }; typedef struct wait_queue_head wait_queue_head_t; wait_queue_head_t my_wait_queue; init_waitqueue_head(&my_wait_queue);
-
阻塞:
#define wait_event_interruptible(wq_head, condition) \ ({ \ int __ret = 0; \ might_sleep(); \ if (!(condition)) \ __ret = __wait_event_interruptible(wq_head, condition); \ __ret; \ }) int wait_event_interruptible(wait_queue_head_t q, CONDITION) /* 如果CONDITION条件为false,则阻塞等待队列中的当前任务 */
-
解除阻塞:
void wake_up_interruptible(wait_queue_head_t *q); /* 如果上述条件为true,则唤醒等待队列中休眠的进程 */
如果想唤醒队列中等待的所有进程,应该使用wake_up_interruptible_all.
#define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)
分类
标签
赞
收藏
回复
相关推荐