linux内核完全剖析 P283页,
内核函数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) //在源代码文件linux/kernel/sched.c中为163行
tmp->state = 0;
}
注释中说在163行之前要加入*p=tmp,其实是错的。首先,当有wake_up()程序唤醒此不可中断睡眠后,是唤醒了整个以*p为队伍头的等待任务队列,所以此时会设置*p = NULL,即睡眠队列不再存在。如果程序运行到了163行,表示此进程已经被唤醒,则说明已经有进程调用了wake_up()函数,此时需要让整个队列上的进程都唤醒,即处于运行状态,即置state为0,而在上面的函数中,tmp实际上就是指向现在队列中还处于睡眠状态的队列头,置其状态为运行状态,当CPU在下一个时间片运行时,就有可能可以被唤醒了,依次下去可以唤醒整个队列。而为什么不能加*p=tmp呢,真正的原因是,当唤醒了一个进程后,如果加上代码*p=tmp,假如此时又有一个进程调用上面的函数要睡眠在这个队列之上,这个任务在sleep_on中的tmp应该指向哪里?显然此时队列中应该只有这个任务,tmp应指向NULL,此时*p应为NULL,所以等待队列要完全重新建立。
注:p为一个全局变量,相当于所有的进程在内核态都可以访问,而tmp为一个局部变量,在每个进程的内核态堆栈中都会有一个值,这个值指向上一个等待的任务,所以队列实际上是由tmp来维护的。
ps1:该死的本书的作者赵炯,竟然分析错了。本来我只是怀疑,在网上一查,果真是书上写错了。
ps2:欣赏linus,这么复杂的算法都想得这么周到,牛
ps3:但对于interrupble_sleep_on函数,linux源代码的确是存在一个问题,(打住吧)。
估计也没什么人能理解这该死的内核代码,RTFSC(read the fucking source code)吧。
>sleep_on注释错误
最新推荐文章于 2024-10-14 16:42:33 发布