code:newproc - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki
- 为当前进程创建子进程
- 父进程返回0
- 子进程返回1
1800 #
1801 /*
1802 */
1803
1804 #include "../param.h"
1805 #include "../user.h"
1806 #include "../proc.h"
1807 #include "../text.h"
1808 #include "../systm.h"
1809 #include "../file.h"
1810 #include "../inode.h"
1811 #include "../buf.h"
1812 /* ------------------------- */
1813 /*
1814 * Create a new process-- the internal version of
1815 * sys fork.
1816 * It returns 1 in the new process.
1817 * How this happens is rather hard to understand.
1820 * in the same call to newproc as the parent;
1821 * but in fact the code that runs is that of swtch.
1822 * The subtle implication of the return value of swtch
1823 * (see above) is that this is the value that newproc's
1824 * caller in the new process sees.
1825 */
1826 newproc()
1827 {
1828 int a1, a2;
1829 struct proc *p, *up;
1830 register struct proc *rpp;
1831 register *rip, n;
1832
1833 p = NULL;
1834 /*
1835 * First, just locate a slot for a process
1837 * The panic "cannot happen" because fork already
1838 * checked for the existence of a slot.
1839 */
1840 retry:
1841 mpid++;
1842 if(mpid < 0) {
1843 mpid = 0;
1844 goto retry;
1845 }
1846 for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
- 为要新建的进程分配一个独一无二的进程标识mpid
- 若为负值,则循环+1,直到其不为负为止
1847 if(rpp->p_stat == NULL && p==NULL)
1848 p = rpp;
1849 if (rpp->p_pid==mpid)
1850 goto retry;
1851 }
1852 if ((rpp = p)==NULL)
1853 panic("no procs");
1854
1855 /*
- 遍历proc数组,将搜索到的第一个空位分配给新进程
- 若遍历时发现有进程的标识等于要分配的标识符,则回到1840行重新分配一个新标识符
- 若没能搜索到空位,则抛出错误
1856 * make proc entry for new proc
1857 */
1858
1859 rip = u.u_procp;
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;
1868 rpp->p_ppid = rip->p_pid;
1869 rpp->p_time = 0;
1870
- 置子进程的proc结构中的相关信息,部分从父进程直接拷贝
- 1868行有笔误,原代码为
rpp->p_ppid = rip->p_ppid
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 /*
- 此处子进程应当申请新的file引用,而不是新的inode引用,未能解释,列入遗留问题
1885 * Partially simulate the environment
1887 * created (by copying) it will look right.
1888 */
1890 rpp = p;
- 将R5,R6保存到u.u_rsav[2]数组中
1891 u.u_procp = rpp;
- rpp指向子进程proc结构
1892 rip = up;
1893 n = rip->p_size;
- rip指向父进程proc结构
1894 a1 = rip->p_addr;
1895 rpp->p_size = n;
1896 a2 = malloc(coremap, n);
- n = 父进程图像大小
- a1 = 父进程的ppda区首址
- 子进程图像大小置为n
1897 /*
- 在内存中为子进程分配一块大小为n的空间,并将该空间的首址赋给a2
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;
1906 xswap(rpp, 0, 0);
1907 rpp->p_flag =| SSWAP;
1908 rip->p_stat = SRUN;
1909 } else {
- 若分配空间失败
- 父进程置状态置为SIDL,接下来将会把父进程图像复制到盘交换区上,在此期间父进程不能被选中上台
- 子进程ppda区指向父进程ppda区首址
- 将R5,R6保存到u.u_ssav[2]数组中
- 在盘交换区上复制一份父进程图像的副本
- 子进程置SSWAP标识,恢复时直接从u.u_ssav[2]数组中恢复R5,R6
- 将父进程置为就绪态,可以被调度进程选中上台
1910 /*
1911 * There is core, so just copy.
1912 */
1913 rpp->p_addr = a2;
1914 while(n--)
1915 copyseg(a1++, a2++);
1916 }
- 若分配空间成功
- 则直接将父进程的图像拷贝一份到新分配的内存空间
1917 u.u_procp = rip;
1918 return(0);
- 恢复父进程上台
1919 }
1920 /* ------------------------- */