#0进程的switch
我们已经了解了进程的switch原理,接下来,我们继续跟踪#0进程,看发生了什么。
1940: sched()
1941: {
……
1951: goto loop;
……
1957: loop:
1958: spl6(); /将cpu priority设置为6
1959: n = -1;
1960: for(rp = &proc[0]; rp < &proc[NPROC]; rp++) /目前,仅有#0和#1两个进程,且都
1961: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && /SLOAD。故,if语句内不会被执行到
1962: rp->p_time > n) {
1963: p1 = rp;
1964: n = rp->p_time;
1965: }
1966: if(n == -1) { /n为-1
1967 runout++;
1968 sleep(&runout, PSWP); /执行sleep,PSWP=-128
1969 goto loop;
1970: }
1971 ……
066: sleep(chan, pri)
2067: {
2068: register *rp, s;
2069:
2070: s = PS->integ;
2071: rp = u.u_procp;
2072: if(pri >= 0) { /调用时,pri = PSWP;
/ <0,故跳过对if内对signal的处理
……
2087: } else {
2088: spl6();
2089: rp->p_wchan = chan;
2090: rp->p_stat = SSLEEP; /#0进程状态改为SSLEEP
2091: rp->p_pri = pri;
2092: spl0();
2093: swtch(); /调用swtch
2094: }
2095: PS->integ = s;
2096: return;
2097: ……
2178: swtch()
2179: {
2180: static struct proc *p;
2181: register i, n;
2182: register struct proc *rp;
2183:
2184: if(p == NULL)
2185: p = &proc[0];
2186: /*
2187: * Remember stack of caller
2188: */
2189: savu(u.u_rsav); /保存当前进程的sp和r5
2190: /*
2191: * Switch to scheduler's stack
2192: */
2193: retu(proc[0].p_addr); /切换到#0进程(当前进程就是#0进程,故此语句其实没有切换进程)
2194:
2195: loop:
2196: runrun = 0;
2197: rp = p;
2198: p = NULL;
2199: n = 128;
2200: /*
2201: * Search for highest-priority runnable process
2202: */
2203: i = NPROC;
2204: do { /在进程表里寻找满足SRUN状态、
2205: rp++; /且flag为SLOAD的进程,如有多
2206: if(rp >= &proc[NPROC]) /个,则选择优先级最高的那个
2207: rp = &proc[0];
2208: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { /事实是,这样的进程只有1个,即
2209: if(rp->p_pri < n) { /我们的#1号进程
2210: p = rp;
2211: n = rp->p_pri;
2212: }
2213: }
2214: } while(--i);
2215: /*
2216: * If no process is runnable, idle.
2217: */
2218: if(p == NULL) { /p指向#1进程,不为NULL
……
2222: }
2223: rp = p;
2224: curpri = n;
2225: /* Switch to stack of the new process and set up
2226: * his segmentation registers.
2227: */
2228: retu(rp->p_addr); /切换到#1进程
2229: sureg();
……
2240: if(rp->p_flag&SSWAP) /显然,if内表达式为false
2241: rp->p_flag =& ~SSWAP; /不会被执行
2242: aretu(u.u_ssav);
2243: }
……/
2247: return(1); /return !!
2248: }
问题出现了——我们并没有为#1进程调用过savu,#1进程会return到哪里去呢?
让我们掉过头来仔细寻找,在newproc()中:
1826 newproc()
……
1889 savu(u.u_rsav); /保存#0的sp和r5(到#0进程的u中)
……
1914 while(n--) /复制#0的私有空间的内容,赋给新进程
1915 copyseg(a1++, a2++); /因此,此时#0的sp和r5也被保存在#1的u中
return(1)将跳回newproc的调用者——main中去!
【思考题】:如果我们想切回#0进程,调用retu的参数应该是什么?
而程序调用后retu后,return语句会跳到哪里?
博客地址:http://blog.csdn.net/cszhao1980
博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html