简体   繁体   English

叉子实施

[英]Fork implementation

How is fork system call code written . fork系统调用代码是如何编写的。 I want to know some details how a function can return two different values and that to two different processes . 我想知道一些函数如何返回两个不同的值以及两个不同的进程的细节。 In short want to know how fork system call is implemented? 总之想知道fork系统调用是如何实现的?

You've pretty much explained it by saying that it's a system call. 你已经通过说这是一个系统调用来解释它。 It's the operating system's job to do all that work, and the operating system can pretty much do whatever it wants outside of the context of your program or the rules of whatever language you're implementing it in. Here's a simple example of how it might happen: 操作系统的所有工作都是操作系统的工作,操作系统几乎可以在程序的上下文之外做任何想做的事情,或者你正在实现它的任何语言的规则。这里有一个简单的例子说明它可能是什么发生:

  1. Program calls fork() system call 程序调用fork()系统调用
  2. Kernel fork system call duplicates the process running the program 内核fork系统调用重复运行程序的进程
  3. The kernel sets the return value for the system call for the original program and for the duplicate (PID of the duplicate and 0, respectively) 内核为原始程序和副本设置系统调用的返回值(重复的PID和0分别)
  4. The kernel puts both processes in the scheduler queue 内核将两个进程都放在调度程序队列中
  5. As each process is scheduled, the kernel 'returns' to each of the two programs. 在安排每个进程时,内核'返回'到两个程序中的每一个。

Carl's answer was great. 卡尔的回答很棒。 I'd like to add that in many operating systems return values are passed in one of the registers. 我想补充一点,在许多操作系统中,返回值在其中一个寄存器中传递。 In x86 architecture this register might be eax, In ARM architecture this register might be R0, etc. 在x86架构中,该寄存器可能是eax,在ARM架构中,该寄存器可能是R0等。

Each process also have a Process Control Block (PCB), which store values of registers at the time some interrupt, syscall, or exception happened and control was passed to the OS. 每个进程还有一个进程控制块(PCB),它在发生某些中断,系统调用或异常并将控制权传递给操作系统时存储寄存器的值。 The next time the process scheduled, the values of the registers are restored from PCB. 下一次调度过程时,寄存器的值将从PCB恢复。

Now, when fork() happens, OS can do: 现在,当fork()发生时,操作系统可以:

 child_process->PCB[return_value_register] = 0;
 parrent_process->PCB[return_value_register] = child_pid;

So, when the processes are rescheduled, each of them see a different return value. 因此,当重新安排流程时,每个流程都会看到不同的返回值。

As an example, you can see xv6's implementation of fork . 举个例子,你可以看到xv6的fork实现 In there, the parent process is still in running state, so it returns parent's return value using simple return statement. 在那里,父进程仍处于运行状态,因此它使用简单的return语句返回父进程的返回值。 But it sets value of EAX register for child process to 0, so when child process is scheduled it sees 0 as return value: 但是它将子进程的EAX寄存器的值设置为0,因此在调度子进程时它将0视为返回值:

// Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0;

Note that return 0 will also compile to something like "mov eax, 0". 请注意,返回0也将编译为类似“mov eax,0”的内容。

Update: I just implemented fork() for a hobby OS I am doing. 更新:我刚刚为我正在做的业余爱好OS实现了fork()。 You can see the source code here . 你可以在这里看到源代码。

There is a comment in the Unix V6 source code booklet for universities which was annotated by Ken Thompson and Dennis Ritchie themselves describing how the double return actually works. 在大学的Unix V6源代码手册中有一条评论,由Ken Thompson和Dennis Ritchie自己描述双重回报实际如何运作。 The comment ends with following sentence: 评论以下列句子结束:

You are not expected to understand this. 你不应该理解这一点。

In easy way for example process is cloned in fork() function with Moving IP/EIP/RIP register to skip some instruction in functions that can look like: 以简单的方式,例如,使用移动IP / EIP / RIP寄存器克隆fork()函数中的进程,以跳过一些函数,这些函数看起来像:

return pid;
return 0;

First process will execute first instruction and pop function from stack, second process will start but from second instruction returning 0. 第一个进程将从堆栈执行第一个指令和弹出函数,第二个进程将从第二个指令返回0开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM