/*
这是一个非常复杂的函数:
该函数与wake_up配合使用,我们用一个例子来说明这个复杂的问题
sleep_on(&inode->i_wait);
比如有任务在等待资源inode->i_wait,如果这个资源是NULL,也就是说,没有任何人在使用这个东西,那么就无需等待,
如果这个队列里面有东西,那么就存在tmp里面,tmp此时指向原等待队列头,值得注意的是,这个地方,tmp是局部变量,而p是全局的。
所有进程共用p , 每个进程都有自己的tmp
讲本进程设置为TASK_UNINTERRUPTIBLE,也就是说调度不会再调度这个进程了,必须要通过wake_up才能重新回来,继续往下跑。
假设现在有3个任务,A,B,C都在等一个资源。调用sleep_on的时间顺序为, C,B,A
此时inode->i_wait的队列头部是A,后来者,在队头。
此时wake_up 将这个队头 置为就绪态,A为就绪态,那么A就可以重新参与调度,
当A被调度的时候,A被唤醒,在A进程中的tmp指向B,把B设置为就绪态,让B重新参与调度。然后A继续往下运行,直到时间到或者发生重新调度。
当B被调度的时候,B被唤醒,在B进程中的tmp指向C,把C设置为就绪态,让C重新参与调度。然后B继续往下运行...
就这样,这个奇怪的唤醒队列,就这样正确的工作了。
这个队列是隐蔽的,这个队列里面的next任务,是存在不同进程的局部变量的,是夸进程的。
*/
//当一个进程所需要的资源正忙,暂时切换出去。
void sleep_on(struct task_struct **p)
{
struct task_struct *tmp;
if (!p)
return;
if (current == &(init_task.task)) //进程0不能睡眠。
panic("task[0] trying to sleep");
tmp = *p;
*p = current;
current->state = TASK_UNINTERRUPTIBLE;//不可中断,这个任务不会在就绪态,不参与本轮调度。
schedule();//这个任务重新被唤醒,才往下执行。这里是嵌套使用的,
if (tmp)
tmp->state=TASK_RUNNING;//置为就绪态,先等的任务先执行。
}
void wake_up(struct task_struct **p)
{
if (p && *p) {
(**p).state=TASK_RUNNING;//置为就绪态。
*p=NULL;
}
}
linux0.11 sleep_on函数说明
猜你喜欢
转载自blog.csdn.net/qq_38307618/article/details/124388200
今日推荐
周排行