先看一下代码:
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;
}
void interruptible_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;
repeat: current->state = TASK_INTERRUPTIBLE;
schedule();
if (*p && *p != current) {
(**p).state=0;
goto repeat;
}
*p=NULL;
if (tmp)
tmp->state=0;
}
void wake_up(struct task_struct **p)
{
if (p && *p) {
(**p).state=0;
*p=NULL;
}
}
先看函数,函数实现很简单。原理有一些抽象,这里先说一下sleep_on函数的应用。
sleep_on函数中只要涉及了:*p,*tmp,current三个人物指针操作。
其中*p表示等待队列头指针,如文件系统i节点的i_wait指针,内存缓冲区操作中的buffer_wait指针;*tmp是临时指针,current代表当前任务指针。
sleep_on函数操作后就形成了一个队列:
tmp指向前一个任务,p指向当前等待队列头,而且每个任务的状态为可中断状态。
注意了,接下来就是我觉得抽象的地方了:
执行wake_up(buffer_wait)时,是怎么唤醒任务的呢?
看函数:
wake_up的操作:
if (p && *p) {
(**p).state=0;
}
把任务状态设置为就绪,之后schedule()函数就会返回到sleep_on函数的最后部分,执行操作如下:
if (tmp)
tmp->state=0;
因为tmp为前一个任务的指针,而且,每次sleep任务时,都创建了tmp指针,所以只要tmp指针不为空,就会把tmp指针指向的任务状态置为就绪。这样就实现了任务的唤醒,从代码看来每次唤醒都是把一个队列中的所有任务唤醒。
interruptible_sleep_on函数类似:
repeat: current->state = TASK_INTERRUPTIBLE;
schedule();
if (*p && *p != current) {
(**p).state=0;
goto repeat;
}
*p=tmp;
if (tmp)
tmp->state=0;
当任务唤醒时,*p指针中有等待任务并且不是当前任务,表示当当前任务放入队列后又有其他任务放入队列中,之后就把当前任务置为就绪,并重新调度。当是当前任务时,也把其他就绪任务也唤醒,同sleep_on函数。
以上就是自己看a代码整理出来了,有任何不对地方,还请留言指正。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)