mirror of
https://github.com/SmallPond/MIT6.828_OS.git
synced 2026-02-03 11:03:16 +08:00
91 lines
2.4 KiB
C
91 lines
2.4 KiB
C
// Ping-pong a counter between two processes.
|
||
// Only need to start one of these -- splits into two, crudely.
|
||
|
||
#include <inc/string.h>
|
||
#include <inc/lib.h>
|
||
|
||
envid_t dumbfork(void);
|
||
|
||
void
|
||
umain(int argc, char **argv)
|
||
{
|
||
envid_t who;
|
||
int i;
|
||
|
||
// fork a child process
|
||
who = dumbfork();
|
||
|
||
// print a message and yield to the other a few times
|
||
for (i = 0; i < (who ? 10 : 20); i++) {
|
||
cprintf("%d: I am the %s!\n", i, who ? "parent" : "child");
|
||
sys_yield();
|
||
}
|
||
}
|
||
|
||
void
|
||
duppage(envid_t dstenv, void *addr)
|
||
{
|
||
int r;
|
||
|
||
// This is NOT what you should do in your fork.
|
||
if ((r = sys_page_alloc(dstenv, addr, PTE_P|PTE_U|PTE_W)) < 0)
|
||
panic("sys_page_alloc: %e", r);
|
||
// dstenv 的 addr 映射到 envs[0]的UTEMP,
|
||
if ((r = sys_page_map(dstenv, addr, 0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0)
|
||
panic("sys_page_map: %e", r);
|
||
|
||
memmove(UTEMP, addr, PGSIZE);
|
||
if ((r = sys_page_unmap(0, UTEMP)) < 0)
|
||
panic("sys_page_unmap: %e", r);
|
||
}
|
||
|
||
envid_t
|
||
dumbfork(void)
|
||
{
|
||
envid_t envid;
|
||
uint8_t *addr;
|
||
int r;
|
||
extern unsigned char end[];
|
||
|
||
// Allocate a new child environment.
|
||
// The kernel will initialize it with a copy of our register state,
|
||
// so that the child will appear to have called sys_exofork() too -
|
||
// except that in the child, this "fake" call to sys_exofork()
|
||
// will return 0 instead of the envid of the child.
|
||
envid = sys_exofork();
|
||
cprintf("envid: %d\n",envid);
|
||
if (envid < 0)
|
||
panic("sys_exofork: %e", envid);
|
||
if (envid == 0) {
|
||
// We're the child.
|
||
// The copied value of the global variable 'thisenv'
|
||
// is no longer valid (it refers to the parent!).
|
||
// Fix it and return 0.
|
||
// "child, sysgetenvid() : 1
|
||
// cprintf("child, sysgetenvid() :%d\n", ENVX(sys_getenvid()));
|
||
thisenv = &envs[ENVX(sys_getenvid())];
|
||
return 0;
|
||
}
|
||
|
||
// We're the parent.
|
||
// Eagerly copy our entire address space into the child.
|
||
// This is NOT what you should do in your fork implementation.
|
||
// 用户程序通常从 UTEXT处开始。
|
||
for (addr = (uint8_t*) UTEXT; addr < end; addr += PGSIZE) {
|
||
// copying addr :00800000
|
||
// copying addr :00801000
|
||
// copying addr :00802000
|
||
cprintf("copying addr :%08x\n", (uint32_t)addr);
|
||
duppage(envid, addr);
|
||
}
|
||
// Also copy the stack we are currently running on.
|
||
duppage(envid, ROUNDDOWN(&addr, PGSIZE));
|
||
|
||
// Start the child environment running
|
||
if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0)
|
||
panic("sys_env_set_status: %e", r);
|
||
|
||
return envid;
|
||
}
|
||
|