我正在阅读“Robert Love的Linux内核开发第3版”,以全面了解Linux内核的工作原理。(2.6.2.3)
我对等待队列如何工作感到困惑,例如这段代码:
/* ‘q’ is the wait queue we wish to sleep on */
DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) { /* condition is the event that we are waiting for */
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if (signal_pending(current))
/* handle signal */
schedule();
}
finish_wait(&q, &wait);
我想知道哪个进程正在运行此代码?它是内核线程吗?谁的处理时间是这个?
并且在循环中,虽然条件仍未满足,但我们将继续睡眠并调用计划以运行另一个进程问题是何时返回此循环?
这本书说,当一个进程休眠时,它会从我们的运行队列中删除,否则它会被唤醒并且必须进入一个繁忙的循环......
我只是想知道这个循环在什么情况下运行?
对不起,如果这是一个愚蠢的问题。我只是很难看到大图片
答案 0 :(得分:6)
哪个进程正在运行代码?调用它的过程。我并不是要取笑这个问题,但要点是内核代码可以在不同的上下文中运行:因为系统调用导致这个地方,因为它在一个中断处理程序中,或者因为它是一个调用的回调函数来自另一个上下文(例如工作队列或计时器功能)。
由于此示例正在休眠,因此它必须位于允许休眠的上下文中,这意味着它是在响应系统调用或至少在内核线程中执行的。所以答案是进程时间取自调用需要休眠的内核代码的进程(或内核线程)。这是唯一一个允许睡觉的地方。
某个特殊情况是工作队列,这些是明确需要睡眠的函数。典型的用途是将需要从禁止睡眠的上下文中休眠的函数排队。在这种情况下,进程上下文是指定用于处理工作队列项的内核工作线程之一。
当wait_queue被唤醒时,你将返回到这个循环,这会将一个任务设置为等待队列运行或所有这些任务,具体取决于所调用的wake_up函数。
最重要的是,除非您对实施细节感兴趣,否则请忘记这一点。由于很多人都犯了这个错误,并且在任何需要的地方基本上都是一样的,因此长期以来一直有宏封装整个过程。查找wait_event(),这就是你的例子应该是这样的:
wait_event(q, condition);
答案 1 :(得分:1)
根据你的例子......我添加了评论......
注意:默认情况下创建等待队列时,它将处于睡眠状态。
DEFINE_WAIT(等待); / *首先等待--->它是指向* /
的内核全局等待队列add_wait_queue(q,& wait); / *首先等待--->它是使用add_wait_queue(q,& wait)指向的内核全局等待队列; --->您正在添加自己的等待队列(如附加链接列表)* /
while(!condition){ / * condition是我们正在等待的事件* / / *条件 - >假设您正在使用write方法从用户空间获取数据(使用__get_user())* /
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
/ *这将在任何wake_up_process()调用生成中断时等待* / if(signal_pending(current))
/ *这是持续监视当前正在运行等待队列的CPU上是否有待处理的信号,而没有等待通常使用的任何信号返回-ERESTARTSYS;或者"打破"循环,如果中断来自exa。,SIGINT或SIGKILL并完成等待队列语句再次检查 / / 处理信号* /
schedule(); // Scheduling of wait queue
// Remove from global data structure
}
finish_wait(& q,& wait); //完成等待队列