2013-10-12 69 views
3

我“由罗伯特·爱的Linux内核开发第3版”,以获取有关Linux内核是如何工作的总体思路阅读。(2.6.2.3)Linux内核 - 等待队列

我感到困惑如何等待队列例如工作验证码:

/* ‘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); 
  • 我想知道哪些进程正在运行该代码?它是一个内核线程?其处理时间是这样的?

  • 以及在循环,而病情依然没有得到满足,我们将继续睡觉,并呼吁时间表运行另一个程序问题是当我们回到这个循环?

  • 书中说,当一个进程睡眠,它是从我们的运行队列中删除,否则会被唤醒,并已经进入一个繁忙的循环......

  • 还说:“睡觉应始终处理一个确保任务等待的条件确实已经发生的循环。“

我只是想在这篇循环运行的情况下知道的吗?

对不起,如果这是一个愚蠢的问题。我只是无法看到的大图

回答

6

哪些进程正在运行的代码?调用它的过程。我并不是想嘲笑这个问题,但要点是内核代码可以在不同的上下文中运行:因为系统调用导致了这个地方,因为它在中断处理程序中,或者因为它是一个称为回调函数来自另一个上下文(例如工作队列或计时器功能)。

由于本例是睡觉,它必须是在睡眠允许一个方面,它是响应于一个系统呼叫或至少在一个内核线程执行的意思。所以答案是从进程(或内核线程)获取进程时间,该进程需要进入需要休眠的内核代码。那是唯一允许睡觉的地方。

某种特殊情况下是工作队列,这些都是明确为需要睡眠功能。典型的用法是将一个需要睡眠的函数从禁止睡眠的上下文中排队。在这种情况下,进程上下文是指定用于处理工作队列项目的内核工作线程之一。

当wait_queue被唤醒,这既可以设定一个任务在等待队列中可运行或全部,这取决于称为WAKE_UP功能,您将返回到这个循环。

最重要的是,忘掉这一点,除非你有兴趣的实施细则。由于许多人得到了这个错误,而且在任何需要的地方都是基本相同的东西,因此长期以来一直封装整个过程的宏。查找wait_event函数(),这是怎么你的榜样应该真正的样子:

wait_event(q, condition); 
+0

欢迎来到SO!伟大的第一个答案 –

+0

谢谢,@BrianCain! –

+1

这不是调度程序的一部分(您可以看到它是_calling_ schedule()),它正在将自己置于睡眠状态。这是一个标准的代码,等待一个wait_queue,直到满足一个条件,这样它的标准被封装在wait_event()中。这比内核抢占要早。 –

1

按你的榜样......我添加了注释....

注:创建默认等待队列会处于睡眠状态。

DEFINE_WAIT(wait);/*首先等待--->它将它指向的内核全局等待队列*/

add_wait_queue(q,& wait);/*首先等待--->它使用add_wait_queue指向的内核全局等待队列(q,& wait); --->你正在添加自己的等待队列(如追加链表)*/

while(!condition){0}条件是我们正在等待的事件*/ /*条件 - >比方说,你在(使用__get_user())*/

prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE); 

/*这将等待时将其中断*/ 如果(signal_pending产生的任何wake_up_process()调用获取的写入方法从用户空间数据(电流))

/*这将持续监视当前CPU是否有任何信号挂起在不等待任何通常使用的信号的情况下运行等待队列返回-ERESTARTSYS;或 “破发” 的循环,如果中断来到EXA,SIGINT或者SIGKILL和完成等待队列语句来再次检查/ /手柄信号*/

schedule(); // Scheduling of wait queue 
       // Remove from global data structure 
} 

finish_wait(& Q,&等待)。 //完成排队