int pid = fork();
if (pid != 0) { /* parent process */
printf("parent is running, child pid:%d\n", pid);
spin("parent");
}
else { /* child process */
printf("child is running, pid:%d\n", getpid());
spin("child");
}
父进程 创建 子进程之后,子进程和 父进程 有相同 代码,都将从 fork 返回,而返回值不同。
PUBLIC int fork()
{
MESSAGE msg;
msg.type = FORK;
send_recv(BOTH, TASK_MM, &msg);// 父进程发的,先发 ,等待接受。因为 子进程 和父进程有相同代码,所以子进程 也在等这个消息。!!!!虽然 没有发!!!
assert(msg.type == SYSCALL_RET);
assert(msg.RETVAL == 0);
return msg.PID;
}
正是 上面函数中的msg 不同,导致了返回值不同。
父进程 给 TASK_MM 发消息,说要fork 子进程,
PUBLIC void task_mm()
{
init_mm();
while (1) {
send_recv(RECEIVE, ANY, &mm_msg);
int src = mm_msg.source;
int reply = 1;
int msgtype = mm_msg.type;
switch (msgtype) {
case FORK:
mm_msg.RETVAL = do_fork();//TASK_MM 接到消息 后开始执行 do_fork
break;
case EXIT:
do_exit(mm_msg.STATUS);
reply = 0;
break;
/* case EXEC: */
/* mm_msg.RETVAL = do_exec(); */
/* break; */
case WAIT:
do_wait();
reply = 0;
break;
default:
dump_msg("MM::unknown msg", &mm_msg);
assert(0);
break;
}
if (reply) {
mm_msg.type = SYSCALL_RET;
send_recv(SEND, src, &mm_msg);
}
}
}
PUBLIC int do_fork()
{
/* find a free slot in proc_table */
struct proc* p = proc_table;
int i;
for (i = 0; i < NR_TASKS + NR_PROCS; i++,p++)
if (p->p_flags == FREE_SLOT)
break;
int child_pid = i;
assert(p == &proc_table[child_pid]);
assert(child_pid >= NR_TASKS + NR_NATIVE_PROCS);
if (i == NR_TASKS + NR_PROCS) /* no free slot */
return -1;
assert(i < NR_TASKS + NR_PROCS);
/* duplicate the process table */
int pid = mm_msg.source;
u16 child_ldt_sel = p->ldt_sel;
*p = proc_table[pid];
p->ldt_sel = child_ldt_sel;
p->p_parent = pid;
sprintf(p->name, "%s_%d", proc_table[pid].name, child_pid);
/* duplicate the process: T, D & S */
struct descriptor * ppd;
/* Text segment */
ppd = &proc_table[pid].ldts[INDEX_LDT_C];
/* base of T-seg, in bytes */
int caller_T_base = reassembly(ppd->base_high, 24,
ppd->base_mid, 16,
ppd->base_low);
/* limit of T-seg, in 1 or 4096 bytes,
depending on the G bit of descriptor */
int caller_T_limit = reassembly(0, 0,
(ppd->limit_high_attr2 & 0xF), 16,
ppd->limit_low);
/* size of T-seg, in bytes */
int caller_T_size = ((caller_T_limit + 1) *
((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ?
4096 : 1));
/* Data & Stack segments */
ppd = &proc_table[pid].ldts[INDEX_LDT_RW];
/* base of D&S-seg, in bytes */
int caller_D_S_base = reassembly(ppd->base_high, 24,
ppd->base_mid, 16,
ppd->base_low);
/* limit of D&S-seg, in 1 or 4096 bytes,
depending on the G bit of descriptor */
int caller_D_S_limit = reassembly((ppd->limit_high_attr2 & 0xF), 16,
0, 0,
ppd->limit_low);
/* size of D&S-seg, in bytes */
int caller_D_S_size = ((caller_T_limit + 1) *
((ppd->limit_high_attr2 & (DA_LIMIT_4K >> 8)) ?
4096 : 1));
/* we don't separate T, D & S segments, so we have: */
assert((caller_T_base == caller_D_S_base ) &&
(caller_T_limit == caller_D_S_limit) &&
(caller_T_size == caller_D_S_size ));
/* base of child proc, T, D & S segments share the same space,
so we allocate memory just once */
int child_base = alloc_mem(child_pid, caller_T_size);
/* int child_limit = caller_T_limit; */
printl("{MM} 0x%x <- 0x%x (0x%x bytes)\n",
child_base, caller_T_base, caller_T_size);
/* child is a copy of the parent */
phys_copy((void*)child_base, (void*)caller_T_base, caller_T_size);
/* child's LDT */
init_desc(&p->ldts[INDEX_LDT_C],
child_base,
(PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT,
DA_LIMIT_4K | DA_32 | DA_C | PRIVILEGE_USER << 5);
init_desc(&p->ldts[INDEX_LDT_RW],
child_base,
(PROC_IMAGE_SIZE_DEFAULT - 1) >> LIMIT_4K_SHIFT,
DA_LIMIT_4K | DA_32 | DA_DRW | PRIVILEGE_USER << 5);
/* tell FS, see fs_fork() */
MESSAGE msg2fs;
msg2fs.type = FORK;
msg2fs.PID = child_pid;
send_recv(BOTH, TASK_FS, &msg2fs);
/* child PID will be returned to the parent proc */
mm_msg.PID = child_pid;// 这里 mm_msg 是个全局变量 ,do_fork 返回后,TASK_MM 给 父进程发消息 返回 子进程的id。
/* birth of the child */
MESSAGE m;
m.type = SYSCALL_RET;
m.RETVAL = 0;
m.PID = 0;
send_recv(SEND, child_pid, &m);// 重点!!注意这是TASK_MM 给 子进程 发的消息,而此刻 子进程在等这个消息。
return 0;
}
如此 ,父进程 和子进程 的到不同返回值。