(萊昂氏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); /儲存sp和r5,下一小節將重點講解
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 }
接下來的幾小節是本章的高潮部分,請稍候。