C语言 在设备驱动程序中调用 set_current_state()/wait_event() 等睡眠函数的影响?



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

以字符设备驱动程序为例,我在 read(( 函数中看到过如下代码,它试图使用set_current_state()(或有时wait_event_interruptible()等(将"进程"置于睡眠状态:

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

在 write 函数或中断处理程序中,它们试图通过将条件设置为 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. 内核代码在发出系统调用的用户空间线程的"内核端"上下文中执行。每个用户空间线程都有这样的内核空间对应物。从调度程序的角度来看,线程的用户和内核部分是同一个实体,因此当内核线程被调度时,用户线程也是如此。

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

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

最新更新