在设备驱动程序中调用诸如set_current_state()/ wait_event()之类的睡眠函数的效果如何?

时间:2018-10-09 04:08:33

标签: c linux-kernel kernel driver

我对内核模块加载到内核后的工作方式有些困惑,主要是因为调用了sleep函数。

以字符设备驱动程序为例,我在read()函数中看到了类似于以下代码的代码,该代码试图使用set_current_state()(有时是wait_event_interruptible()等)使“进程”进入休眠状态。 :

set_current_state(TASK_INTERRUPTIBLE);
task = current;
for(;;)
{
    if(condition)
        break;
    schedule();
}
set_current_state(TASK_RUNNING);

在写函数或中断处理程序中,他们试图通过将条件设置为true来唤醒read(),

condition = true;
wake_up_process(task); // -> task was stored inside read() function

我的问题是:

  1. set_current_state()wait_event_interruptible()哪个睡眠在这里?是用户空间进程调用系统调用read()还是为了映射用户空间进程而创建的某个内核进程?

  2. 假定通过在open()函数中设置原子计数,此设备驱动程序访问仅限于一个进程,并且该设备驱动程序未启用中断,如果read()调用wait_event()会发生什么情况真的没有其他进程可以唤醒它吗?它会永远卡住(因为没有中断)吗?

  3. 使用set_current_state()wait_event() API有什么区别?我已经看到了相应地使用这些函数的不同代码段...我应该考虑一个相对于另一个的偏好吗?

1 个答案:

答案 0 :(得分:0)

  1. 内核代码在发出系统调用的用户空间线程的“内核侧”上下文中执行。每个用户空间线程都有相应的内核空间。从调度程序的角度来看,线程的用户部分和内核部分是同一实体,因此在调度内核线程时,用户线程也是如此。

  2. “可中断”和“不可中断”等待的不同之处在于信号的处理方式。当进程处于TASK_INTERRUPTIBLE状态并获取信号时,系统确保它尽快从schedule()唤醒。之后,如果signal_pending()返回true,则进程本身必须离开等待循环。在问题文本的示例代码中,除非“ condition”是包含signal_pending()检查的表达式,否则无法正确实现。

  3. set_current_state()是当前进程状态的setter调用,它仅设置一个标志,不执行其他任何操作。它只能与对schedule()的正确调用一起使用。 wait_event()是一个实用程序,可实现所有等待的技术细节。通常,驱动程序使用wait_event *()风格,仅在特殊情况下才需要直接使用set_current_state()和schedule()。