sys_fork() in os161

$Id: os161-sys_fork.html,v 1.5 2005/10/07 02:43:44 george Exp $

sys_fork() in os161

Description

fork duplicates the currently running process. The two copies are identical, except that one (the "new" one, or "child"), has a new, unique process id, and in the other (the "parent") the process id is unchanged.

The process id must be greater than 0.

The two processes do not share memory or open file tables; this state is copied into the new process, and subsequent modification in one process does not affect the other.

However, the file handle objects the file tables point to are shared, so, for instance, calls to lseek in one process can affect the other.

Return Values

On success, fork returns twice, once in the parent process and once in the child process. In the child process, 0 is returned. In the parent process, the process id of the new child process is returned.

On error, no new process is created, fork only returns once, returning -1, and errno is set according to the error encountered.

Step

When doing a fork there are a number of things to do for the child process. Copy the currently running thread:

  1. Create child process.
    	newguy = thread_create( curthread->t_name );
  2. Create a new kernel stack in t_stack.
  3. Copy cwd.
    	/* Inherit the current directory */
    if (curthread->t_cwd != NULL) {
    VOP_INCREF(curthread->t_cwd);
    newguy->t_cwd = curthread->t_cwd;
    }
  4. Clone the open file handles, this is implementation specific and relatively easy to do.

    for-loop works for the simple condition.

  5. Copy user stack, text and data segments from parent process to child process.
    	/* Allocate a stack */
    newguy->t_stack = kmalloc(STACK_SIZE);
    if (newguy->t_stack==NULL) {
    kfree(newguy->t_name);
    kfree(newguy);
    return ENOMEM;
    }
  6. Create a new pcb by running md_initpcb.

    md_forkentry is looking promising as the function.

    	/* Set up the pcb (this arranges for func to be called) */
    newguy->t_pcb = curthread->t_pcb;

    md_initpcb( &newguy->t_pcb, newguy->t_stack, tf, 0, md_forkentry );

  7. Copy the trapframe onto the new threads kernel stack in md_forkentry().
  8. Make the new thread runnable and let it return via md_forkentry.

Race Condition

When debuging, It is a very interesting that scheduler doesn't schedule child process to run although child process is in the runqueue until parent process completes printing text. So we should lock off parent process prior to child process setup.

md_entry( struct trapframe * parent_tf ) is the very function called when child process starts to run.

child process trapframe can only be declared on child process kernel stack like md_usermode() does.

parent_tf points to the specific address which is the same in every exception handling. It is too late to access the original parent process's trapframe when child process is running. Because parent process call printf function which invokes several system call sys_write one for each character in printf.

Parent process trapframe at that time is different from the one in sys_fork() which is what child process actually needs. In order to preserve that trapframe, we should set up child process own trapframe and copy parent process trapframe before parent process invokes any other system call.

Lock off parent process using P( forksem ) before sys_fork() return and V( forksem ) in md_forkentry() after child process trapframe set.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值