linux0.11 sleep_on函数说明

/*
这是一个非常复杂的函数:
该函数与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;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_38307618/article/details/124388200