1. 程式人生 > >(萊昂氏unix原始碼分析導讀-11)系統初啟(4)

(萊昂氏unix原始碼分析導讀-11)系統初啟(4)

本章討論程序複製,繼續Main函式。

1625 */

1626

1627 if(newproc()) {                        

……

現在看newproc的程式碼。

1826 newproc()

1827 {

          ......

1840 retry:

1841     mpid++;                                                                              /生成程序Id

1842     if(mpid < 0) {

1843             mpid = 0;

1844             goto retry;

1845     }

1846     for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {     /這個for迴圈有兩重意思

1847             if(rpp->p_stat == NULL & && p==NULL)       

1848                           p = rpp;                                                       /1)在程序描述表內選取一個空表項;

1849                          if (rpp->p_pid==mpid)                                /2)檢查剛生成的程序Id是否為唯一

1850                                                 goto retry;

1851      }

1852      if ((rpp = p)==NULL)                                                      /程序表滿,Error

1853                 panic("no procs");

1854

1855      /*

1856       * make proc entry for new proc

1857       */

1858                                                            /rpp為新挑選的空表項

1859      rip = u.u_procp;                           /rip為當前process(即#0程序)的程序表項

1860      up = rip;                                   

1861      rpp->p_stat = SRUN;                  /開始設定新表項的資訊

1862      rpp->p_flag = SLOAD;

1863      rpp->p_uid = rip->p_uid;            /很多資訊都與當前程序的設定一樣

1864      rpp->p_ttyp = rip->p_ttyp;

1865      rpp->p_nice = rip->p_nice;

1866      rpp->p_textp = rip->p_textp;

1867      rpp->p_pid = mpid;                         /程序Id

1868      rpp->p_ppid = rip->p_pid;            /新程序的父程序為當前程序(#0程序)

1869      rpp->p_time = 0;

1870

1871     /*

1872      * make duplicate entries

1873      * where needed

1874     */

1875

1876     for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];)   /--

1877           if((rpp = *rip++) != NULL)

1878                   rpp->f_count++;

1879     if((rpp=up->p_textp) != NULL) {                                 /參見萊昂註釋

1880           rpp->x_count++;

1881           rpp->x_ccount++;

1882     }

1883     u.u_cdir->i_count++;                                                       --/

1884     /*

1885      * Partially simulate the environment

1886      * of the new process so that when it is actually

1887      * created (by copying) it will look right.

1888      */

1889      savu(u.u_rsav);                             /儲存spr5,下一小節將重點講解

1890      rpp = p;

1891      u.u_procp = rpp;                           /暫時更改u_procp,使其指向新程序表項

1892      rip = up;                                        /rip指向#0程序

1893      n = rip->p_size;

1894      a1 = rip->p_addr;

1895      rpp->p_size = n;                           /設定新程序的“私有空間”長度(單位:block

1896      a2 = malloc(coremap, n);               /為新程序分配“私有空間”

1897      /*

1898       * If there is not enough core for the

1899       * new process, swap put the current process to

1900       * generate the copy.

1901       */

1902       if(a2 == NULL) {                           /--

1903             rip->p_stat = SIDL;                  /    

1904             rpp->p_addr = a1;                     /空間不夠系統初啟時,不會發生這種情況,

1905             savu(u.u_ssav);                          /故先跳過

1906             xswap(rpp, 0, 0);

1907             rpp->p_flag =| SSWAP;

1908             rip->p_stat = SRUN;                 --/

1909       } else {

1910       /*

1911        * There is core, so just copy.

1912        */

1913             rpp->p_addr = a2;                 /設定新程序的“私有空間”地址——新程序誕生了!

1914             while(n--)                              /複製#0的私有空間的內容,賦給新程序

1915                  copyseg(a1++, a2++);     / copyseg是我們的老朋友了

1916      }                                   

1917      u.u_procp = rip;                          /恢復u_procp,使其指向#0程序

1918      return(0);                                     /返回值為0

1919 }

看來,newproc()函式並沒有執行什麼神奇魔法,它生成了一個與#0幾乎一模一樣的新程序。

但是,cpu仍在#0手中,新程序尚未得到執行。

回到main函式:

1627 if(newproc()) {                              /返回值為0,故此if語句內都不會被執行

1628      expand(USIZE+1);                   

1629      estabur(0, 1, 0, 0);   

1630      copyout(icode, 0, sizeof icode);

1631      /*

1632           * Return goes to loc. 0 of user init

1633           * code just copied out.

1634      */

1635      return;

1636 }

1637  sched();                                     /執行sched,下小節討論

1638 }

接下來的幾小節是本章的高潮部分,請稍候。