叉子实施

Utk*_*tav 9 c unix operating-system systems-programming

fork系统调用代码是如何编写的.我想知道一些函数如何返回两个不同的值以及两个不同的进程的细节.总之想知道fork系统调用是如何实现的?

Car*_*rum 10

你已经通过说这是一个系统调用来解释它.操作系统的所有工作都是操作系统的工作,操作系统几乎可以在程序的上下文之外做任何想做的事情,或者你正在实现它的任何语言的规则.这里有一个简单的例子说明它可能是什么发生:

  1. 程序调用fork()系统调用
  2. 内核fork系统调用重复运行程序的进程
  3. 内核为原始程序和副本设置系统调用的返回值(重复的PID和0分别)
  4. 内核将两个进程都放在调度程序队列中
  5. 在安排每个进程时,内核'返回'到两个程序中的每一个.


Had*_*edi 10

卡尔的回答很棒.我想补充一点,在许多操作系统中,返回值在其中一个寄存器中传递.在x86架构中,该寄存器可能是eax,在ARM架构中,该寄存器可能是R0等.

每个进程还有一个进程控制块(PCB),它在发生某些中断,系统调用或异常并将控制权传递给操作系统时存储寄存器的值.下一次调度过程时,寄存器的值将从PCB恢复.

现在,当fork()发生时,操作系统可以:

 child_process->PCB[return_value_register] = 0;
 parrent_process->PCB[return_value_register] = child_pid;
Run Code Online (Sandbox Code Playgroud)

因此,当重新安排流程时,每个流程都会看到不同的返回值.

举个例子,你可以看到xv6的fork实现.在那里,父进程仍处于运行状态,因此它使用简单的return语句返回父进程的返回值.但是它将子进程的EAX寄存器的值设置为0,因此在调度子进程时它将0视为返回值:

// Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0;
Run Code Online (Sandbox Code Playgroud)

请注意,返回0也将编译为类似"mov eax,0"的内容.

更新:我刚刚为我正在做的业余爱好OS实现了fork().你可以在这里看到源代码.