linux-0.11中进程睡眠函数sleep_on()解析


sleep_on()用于进程睡眠。

其原型为

void sleep_on(struct task_struct **p);

比如某个资源是互斥的,当资源被某一个进程占用时,其他进程便无法访问此资源。

假设资源结构为

struct __xxx_resource

{

       struct resource *rs;
       struct task_struct *wait;
       ....

}xxx_resource;

那么若某进程无法得到资源,其使用
sleep_on(&wait) 在资源的wait队列上睡眠,注意到这里的wait只是指针变量,那么多个进程调用sleep_on()是如何形成所谓的wait队列呢?以下是我的一些理解。
sleep_on()函数原型如下

void sleep_on(struct task_struct **p)
{
   struct task_struct *tmp;

   if (!p)
      return;
   if (current == &(init_task.task))
      panic("task[0] trying to sleep");
   tmp = *p; 
   *p = current;
   current->state = TASK_UNINTERRUPTIBLE;
   schedule();
   if (tmp)
      tmp->state=0;
}
函数流程比较简单,先做了一些基本的判断,然后使用一个tmp变量指向*p,*p指向当前的进程,设置进程标志为TASK_UNINTERRUPTIBLE即不可中断睡眠,随后就执行schedule()调度其他进程运行,当本进程恢复运行时,设置tmp->state为0即TASK_RUNNING。

让我们用例子来理解sleep_on()
假设有2个进程A,B都无法访问资源,只能执行sleep_on(&wait)进行睡眠。
1. 进程A执行sleep_on(&wait),进入睡眠,tmp -> wait'(NULL),wait'' -> 进程A task_struct
2. 进程B执行sleep_on(&wait),进入睡眠,tmp -> wait'',wait''' -> 进程B task_struct

wait上标表示wait值的不同。
可以看到wait始终指向的是最后一个执行sleep_on()的进程task_struct。

理解的关键在于:所有的进程共用一个公有的wait变量(因为资源只有一个),然而内部的tmp变量是进程私有的,(tmp变量在栈中分配),便是私有的tmp和公有的wait形成了等待队列,而wait可以看成是等待队列的第一个成员,tmp则指向等待队列的第二个成员。

当资源被释放,使用wake_up(&wait)唤醒等待队列上的睡眠进程,过程则如下
1. wait指向进程B的task_struct,则进程B被唤醒。
2. 进程B唤醒后,执行if (tmp) tmp->state = 0,进程B上下文中的tmp是指向进程A的task_struct,则进程A被唤醒。
3. 进程A被进程B唤醒。

可以发现,调用了wake_up(&wait)之后,在等待队列上睡眠的所有进程都被唤醒了,以一种“链式”的方式。

你可能感兴趣的:(linux-0.11中进程睡眠函数sleep_on()解析)