Linux 设备驱动程序 3Ed 文件 IO 以及如何使用解释性 UML 图影响调度

Linux Device Drivers 3Ed File IO & How to Influence Scheduling with Explanatory UML Diagrams

我使用 UMLet 绘制了一些 UML 图,描述了 Linux Device Drivers 3Ed (LDD3) 的每一章的各种实体关系,作者是 Corbet、Rubini、Kroah-Hartman。最新版本的图表可以在这里找到:

Linux Device Drivers 3Ed UML Diagrams

我想请求帮助理解上面链接的非阻塞文件 IO 序列图中的文档支持的调度问题,以及 P156-158 上的 LDD3,特别是这段代码scull_getwritespace() 的片段(另见 P156,但此代码已更新为使用互斥量而不是信号量):

/* Wait for space for writing; caller must hold device semaphore.  On
 * error the semaphore will be released before returning. */
static int scull_getwritespace(struct scull_pipe *dev, struct file *filp)
{
 while (spacefree(dev) == 0) { /* full */
  DEFINE_WAIT(wait);
  
  mutex_unlock(&dev->mutex);
  if (filp->f_flags & O_NONBLOCK)
   return -EAGAIN;
  PDEBUG("\"%s\" writing: going to sleep\n",current->comm);
  prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
  if (spacefree(dev) == 0)
   schedule();
  finish_wait(&dev->outq, &wait);
  if (signal_pending(current))
   return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  if (mutex_lock_interruptible(&dev->mutex))
   return -ERESTARTSYS;
 }
 return 0;
} 

特别是:

if(spacefree(dev) == 0)
  schedule();

感兴趣的案例是这样的:

  1. spacefree(dev) == 0 为真,写入进程即将调用schedule()。
  2. 在调用 schedule() 之前,读取进程发出 wake_up_interruptible(&dev->outq) 已经消耗了所有缓冲区数据,因此应该唤醒写入进程,以便它可以产生更多数据。这会将写入进程状态设置回 TASK_RUNNING.
  3. 写入进程调用 schedule() 并可能进入睡眠状态。

以上是为了避免竞争条件。

这是我的问题:

  1. 是否可以修改内核的 code/operation 以便我可以保证 schedule() 不会进入休眠状态而是 returns 立即从调用开始?我对 schedule() 的理解不够详细,无法回答这个问题,我们将不胜感激。我认为答案是否定的,因为调度程序可以选择接下来发生的事情,并且可能有软件中断、微线程或信号要处理。
  2. 是否可以修改代码,保证在重新进入读进程之前写进程运行?同样,我认为答案可能是否定的,但也许线程优先级有一些可能性。

我发现 linux 内核实体的图形表示对于理解内核中的模式非常有帮助,这大大提高了我的编码效率,但是手工生成它们非常乏味。为了节省时间,有没有其他人针对 LDD3 做过类似的事情?

谢谢。

不确定您是否有机会进入内核映射http://www.makelinux.net/kernel_map/