```Java โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ็ˆถ่ฟ›็จ‹ (ๅœจ็”จๆˆทๆ€) ่ฐƒ็”จ fork() โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ | | (่งฆๅ‘็ณป็ปŸ่ฐƒ็”จ๏ผŒ่ฟ›ๅ…ฅๅ†…ๆ ธ) v โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ (็ˆถ่ฟ›็จ‹ๅ†…ๆ ธๆ€) ๆ‰ง่กŒ fork(): โ”‚ โ”‚ โ”‚ โ”‚ 1) p = myproc(); // ๆ‹ฟๅˆฐๅฝ“ๅ‰(็ˆถ)่ฟ›็จ‹ p โ”‚ โ”‚ 2) np = allocproc(); // ๅˆ†้…ๅนถๅˆๅง‹ๅŒ–ๅญ่ฟ›็จ‹ np โ”‚ โ”‚ 3) uvmcopy(...); // ๆ‹ท่ด็ˆถ่ฟ›็จ‹ๅ†…ๅญ˜็ป™ๅญ่ฟ›็จ‹ โ”‚ โ”‚ 4) np->trapframe->a0 = 0; // "ๅญ่ฟ›็จ‹"็š„่ฟ”ๅ›žๅ€ผๅฏ„ๅญ˜ๅ™จ่ฎพไธบ 0 โ”‚ โ”‚ 5) for(i=0..NOFILE) filedup(...) // ๅคๅˆถๆ–‡ไปถๆ่ฟฐ็ฌฆ็ป™ๅญ่ฟ›็จ‹ โ”‚ โ”‚ np->cwd = idup(p->cwd); // ๅคๅˆถๅทฅไฝœ็›ฎๅฝ• โ”‚ โ”‚ safestrcpy(np->name, p->name); // ๅญ่ฟ›็จ‹็ปงๆ‰ฟๅๅญ— โ”‚ โ”‚ 6) pid = np->pid; // ่ฎฐๅฝ•ๅญ่ฟ›็จ‹็š„PID โ”‚ โ”‚ 7) np->state = RUNNABLE; // ๅญ่ฟ›็จ‹็ฝฎไธบๅฐฑ็ปช โ”‚ โ”‚ 8) return pid; // ๅ†…ๆ ธๆ€่ฟ”ๅ›ž pid โ†’ ็ˆถ่ฟ›็จ‹็”จๆˆทๆ€ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ | | (ๅˆ‡ๆขๅ›ž็ˆถ่ฟ›็จ‹็”จๆˆทๆ€) v โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ็ˆถ่ฟ›็จ‹็”จๆˆทๆ€ๅพ—ๅˆฐ fork() == pid โ”‚ โ”‚ (็ˆถ่ฟ›็จ‹็ปง็ปญๆ‰ง่กŒ่‡ชๅทฑ็š„ๅŽ็ปญไปฃ็ ) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ---- (ๅˆ†ๅ‰ฒ็บฟ) ---- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๅญ่ฟ›็จ‹ๆญคๆ—ถๅนถๆฒกๆœ‰"ๆ‰ง่กŒ fork() ๅ‡ฝๆ•ฐ" โ”‚ โ”‚ ๅฎƒๅชๆ˜ฏ่ขซๅ†…ๆ ธๆ”พๅˆฐไบ†ๅฏ่ฟ่กŒ้˜Ÿๅˆ— (RUNNABLE)๏ผŒๅนถ่ฟ˜ๆฒก็œŸๆญฃ่ฟ่กŒใ€‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ | | (่ฐƒๅบฆๅ™จๅˆ‡ๆขๅˆฐๅญ่ฟ›็จ‹) v โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ ๅญ่ฟ›็จ‹"ไธŠ CPU"ๆ—ถ๏ผŒไปŽ็”จๆˆทๆ€่ง†่ง’็œ‹๏ผŒ่‡ชๅทฑๅฐฑๅƒ"ไปŽ fork() ่ฟ”ๅ›ž"๏ผš โ”‚ โ”‚ โ”‚ โ”‚ trapframe->a0 = 0 --> fork() ็š„่ฟ”ๅ›žๅ€ผ==0 โ”‚ โ”‚ โ”‚ โ”‚ ๅญ่ฟ›็จ‹ๅ…ถๅฎžๆ˜ฏๅœจ"็”จๆˆทๆ€็š„ fork() ่ฐƒ็”จ็‚นไน‹ๅŽ"็ปง็ปญๆ‰ง่กŒ๏ผŒ โ”‚ โ”‚ ่‡ชๅทฑ็œ‹ๅˆฐ fork() ็š„่ฟ”ๅ›žๅ€ผๆ˜ฏ 0 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ## ็ˆถ่ฟ›็จ‹่ง†่ง’ ```c // Create a new process, copying the parent. // Sets up child kernel stack to return as if from fork() system call. int fork(void) { int i, pid; struct proc *np; struct proc *p = myproc(); //Process p = Process.currentProcess(); // Allocate process. if((np = allocproc()) == 0){ return -1; //่ฟ”ๅ›ž -1 ่กจ็คบ้”™่ฏฏ } // Copy user memory from parent to child. // ๅคๅˆถๅ†…ๅญ˜็ฉบ้—ด np.setMemory(p.getMemory().clone()); if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ freeproc(np); release(&np->lock); return -1; } np->sz = p->sz; np->parent = p; //np.setParent(p); np->mask = p->mask; //np.setMask(p.getMask()); // copy saved user registers. *(np->trapframe) = *(p->trapframe); // Cause fork to return 0 in the child. // ไฟฎๆ”นๅญ่ฟ›็จ‹่ฟ™่พน็š„่ฟ”ๅ›žๅ€ผ๏ผŒ // ็ˆถ่ฟ›็จ‹ๆ‹ฟๅˆฐ็š„ fork() ่ฟ”ๅ›žๅ€ผๆ˜ฏ pid๏ผŒๅญ่ฟ›็จ‹ๅˆ™ๆ˜ฏ 0ใ€‚่ฟ™ๆ˜ฏ Unix fork() ็š„็ปๅ…ธ่ฏญไน‰ใ€‚ np->trapframe->a0 = 0; // increment reference counts on open file descriptors. for(i = 0; i < NOFILE; i++) if(p->ofile[i]) // child.openFiles[i] = new FileDescriptor(parent.openFiles[i]) np->ofile[i] = filedup(p->ofile[i]); np->cwd = idup(p->cwd); safestrcpy(np->name, p->name, sizeof(p->name)); pid = np->pid; np->state = RUNNABLE; release(&np->lock); return pid; } ``` ## ๅญ่ฟ›็จ‹่ง†่ง’ ```c // ๅœจๅญ่ฟ›็จ‹ trapframe ไธญๅฐ† a0 ่ฎพไธบ 0 np->trapframe->a0 = 0; ``` ่ฟ™ไธ€ๅˆ‡้ƒฝๅช้œ€่ฆๅ†…ๆ ธๅœจ**็ˆถ่ฟ›็จ‹็š„"fork"ไปฃ็ **้‡ŒๆŠŠๅญ่ฟ›็จ‹็š„่ฟ่กŒ็Žฐๅœบ๏ผˆtrapframe๏ผ‰"ๆ‘†ๅผ„"ๅฅฝๅณๅฏ๏ผŒๅญ่ฟ›็จ‹**ไธไผš**ๅœจๅ†…ๆ ธ้‡Œๅ†ๅŽป"่ตฐไธ€้"ๅŽ็ปญ็š„่ต‹ๅ€ผใ€ๅพช็Žฏใ€return ็ญ‰ C ไปฃ็ ใ€‚ ## ไธบไป€ไนˆๅญ่ฟ›็จ‹ๆ‹ฟๅˆฐ็š„ fork() ่ฟ”ๅ›žๅ€ผ 0 1. RISC-V ๆžถๆž„ไธญๅ‡ฝๆ•ฐ่ฟ”ๅ›žๅ€ผไฟๅญ˜ๅœจ `a0` 2. ่ฟ™ๅฐฑ่ฎฉๅญ่ฟ›็จ‹็š„ๅฏ„ๅญ˜ๅ™จ `a0` ่ขซๅผบ่กŒ็ฝฎๆˆ `0`ใ€‚ 3. ๅœจ Unix ็š„่ฟ›็จ‹ๆจกๅž‹ไธญ๏ผŒ"ๅญ่ฟ›็จ‹"่ฏž็”Ÿๆ—ถไป…ไป…ๆ˜ฏใ€Œๅคๅˆถไบ†็ˆถ่ฟ›็จ‹็š„ๅœฐๅ€็ฉบ้—ดๅ’Œๅ†…ๆ ธไธŠไธ‹ๆ–‡ใ€๏ผŒ่‡ชๅทฑ**่ฟ˜ๆฒก็œŸๆญฃ่Žทๅพ— CPU ๆ‰ง่กŒๆ—ถ้—ด**ใ€‚ๅฎƒๅชๆœ‰ๅœจๅ†…ๆ ธๆŠŠๅฎƒๆ ‡่ฎฐไธบ `RUNNABLE` ไน‹ๅŽ๏ผŒ่ฐƒๅบฆๅ™จๆ‰่ƒฝๅœจๅฐ†ๆฅๆŸไธชๆ—ถๅˆป"ๅˆ‡ๆข"ๅˆฐๅญ่ฟ›็จ‹๏ผŒ่ฎฉๅฎƒ**ไปŽ็”จๆˆทๆ€**่ท‘่ตทๆฅใ€‚ 4. ็ญ‰ๅญ่ฟ›็จ‹่ฆ"่ฟ”ๅ›žๅˆฐ็”จๆˆทๆ€"ๆ—ถ๏ผŒไผšๆŠŠ `a0` ็š„ๅ€ผๅธฆๅˆฐๅญ่ฟ›็จ‹็š„ C ่ฐƒ็”จๆ ˆ็Žฏๅขƒ๏ผŒ**ไปŽ่€Œๅญ่ฟ›็จ‹็œ‹ๅˆฐ็š„ `fork()` ่ฟ”ๅ›žๅ€ผๆ˜ฏ 0**ใ€‚ ไนŸๅฐฑๆ˜ฏ่ฏด๏ผŒ่ฟ™ไบ›"ๆ‹ท่ดๅ†…ๅญ˜ใ€่ฎพ็ฝฎๅฏ„ๅญ˜ๅ™จใ€่ฎพ็ฝฎ่ฟ”ๅ›žๅ€ผ"็š„ๅŠจไฝœ๏ผŒ**ๆœฌ่ดจๆ˜ฏ็ˆถ่ฟ›็จ‹ๅœจๅนฒ**๏ผŒๅญ่ฟ›็จ‹ๅนถไธ้œ€่ฆ"ไบฒๅŠ›ไบฒไธบ"ใ€‚ ๅ› ๆญค๏ผŒไป…ๅ‡ญ ```c np->trapframe->a0 = 0; // ๅฏนๅญ่ฟ›็จ‹่ฎพ็ฝฎ่ฟ”ๅ›žๅ€ผ return pid; // ๅฏน็ˆถ่ฟ›็จ‹่ฎพ็ฝฎ่ฟ”ๅ›žๅ€ผ ``` ๅฐฑ่ƒฝๅœจ็ˆถๅญไธคไธช่ฟ›็จ‹ไธญไฝ“็ŽฐไธๅŒ็š„่ฟ”ๅ›žๅ€ผ๏ผŒ่พพๆˆ Unix `fork()` ็š„"ไธ€ๆฌก่ฐƒ็”จใ€ไธคๆฌก่ฟ”ๅ›ž"ๆ•ˆๆžœใ€‚