(莱昂氏unix源代码分析导读-13)系统初启(6)

 #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);                                                            /执行sleepPSWP=-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);                                            /保存当前进程的spr5

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++;                                                                                        /flagSLOAD的进程,如有多

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);                                          /保存#0spr5(到#0进程的u中)

……

1914             while(n--)                                           /复制#0的私有空间的内容,赋给新进程

1915                  copyseg(a1++, a2++);                  /因此,此时#0spr5也被保存在#1u

 

return(1)将跳回newproc的调用者——main中去!

 

【思考题】:如果我们想切回#0进程,调用retu的参数应该是什么?

                        而程序调用后retu后,return语句会跳到哪里?

 

  博客地址:http://blog.csdn.net/cszhao1980

 博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

 

你可能感兴趣的:(unix,struct,null,search,Signal,代码分析)