void interruptible_sleep_on (struct task_struct **p)// **p是个全局变量 { struct task_struct *tmp; if (!p)#没有进程等待就返回 return; if (current == &(init_task.task)) panic ("task[0] trying to sleep"); tmp = *p;#在自己的内核堆栈中,暂时保存原来保存在**p中的进程,因为调度时,还没有退出interruptible_sleep_on函数 *p = current;#**p保存当前进程 repeat: current->state = TASK_INTERRUPTIBLE;#改变当前进程状态 schedule (); // 如果等待队列中还有等待任务,并且队列头指针所指向的任务不是当前任务时,则将该等待任务置为 // 可运行的就绪状态,并重新执行调度程序。当指针*p 所指向的不是当前任务时,表示在当前任务被放 // 入队列后,又有新的任务被插入等待队列中,因此,既然本任务是可中断的,就应该首先执行所有 // 其它的等待任务。 if (*p && *p != current)#可能有其他进程调用该函数 { (**p).state = 0; goto repeat; } // 下面一句代码有误,应该是*p = tmp,让队列头指针指向其余等待任务,否则在当前任务之前插入 // 等待队列的任务均被抹掉了。参见图4.3。 *p = NULL; if (tmp) tmp->state = 0; }
sleep_if_full (struct tty_queue *queue) { // 若队列缓冲区不满,则返回退出。 if (!FULL (*queue)) return; cli (); // 关中断。 // 如果进程没有信号需要处理并且队列缓冲区中空闲剩余区长度<128,则让进程进入可中断睡眠状态, // 并让该队列的进程等待指针指向该进程。 while (!current->signal && LEFT (*queue) < 128) interruptible_sleep_on (&queue->proc_list);//队列的进程列表,保存的是pcb指针 sti (); // 开中断。 } //// 等待按键。 // 如果控制台的读队列缓冲区空则让进程进入可中断的睡眠状态。 void wait_for_keypress (void) { sleep_if_empty (&tty_table[0].secondary); }
浙公网安备 33010602011771号