Python:os.fork() 如何工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33560802/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python:How os.fork() works?
提问by tudouya
I am learning multiprocessing in python. I tried multiprocessing and after I read the source code of multiprocessing module, I found it use os.fork()
, so I wrote some code to test os.fork()
, but I am stuck. My code is as following:
我正在学习 python 中的多处理。我尝试了 multiprocessing ,在阅读 multiprocessing 模块的源代码后,我发现它有用os.fork()
,所以我写了一些代码来测试os.fork()
,但我卡住了。我的代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import time
for i in range(2):
print '**********%d***********' % i
pid = os.fork()
print "Pid %d" % pid
I think that each print will be executed two times but they execute three times. I can't understand how this works?
I read this Need to know how fork works?
From what this article says it also will be executed twice, so I am so stuck...
我认为每次打印都会执行两次,但它们会执行三次。我无法理解这是如何工作的?我读过这篇文章需要知道 fork 是如何工作的吗?
从这篇文章说它也将被执行两次,所以我被困住了......
采纳答案by glglgl
To answer the question directly, os.fork()
works by calling the underlying OS function fork()
.
要直接回答问题,请os.fork()
调用底层 OS 函数fork()
。
But you are surely interested in what this does. Well this creates another process which will resume at exactly the same place as this one. So within the first loop run, you get a fork after which you have two processes, the "original one" (which gets a pid
value of the PID of the child process) and the forked one (which gets a pid
value of 0
).
但你肯定对它的作用感兴趣。那么这将创建另一个进程,它将在与这个进程完全相同的位置恢复。因此,在第一个循环运行中,您会得到一个 fork,之后您有两个进程,“原始进程”(获取pid
子进程的 PID 值)和分叉的进程(获取pid
值0
)。
They both print their pid
value and go on with the 2nd loop run, which they both print. Then they both fork, leaving you with 4 processes which all print their respective pid
values. Two of them should be 0
, the other two should be the PIDs of the child they just created.
他们都打印他们的pid
值并继续第二次循环运行,他们都打印了。然后他们都分叉,给你留下 4 个进程,它们都打印各自的pid
值。其中两个应该是0
,另外两个应该是他们刚刚创建的孩子的PID。
Changing the code to
将代码更改为
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import time
for i in range(2):
print '**********%d***********' % i
pid = os.fork()
if pid == 0:
# We are in the child process.
print "%d (child) just was created by %d." % (os.getpid(), os.getppid())
else:
# We are in the parent process.
print "%d (parent) just created %d." % (os.getpid(), pid)
you will see better what happens: each process will tell you its own PID and what happened on the fork.
你会更清楚地看到发生了什么:每个进程都会告诉你它自己的 PID 以及在 fork 上发生了什么。
回答by 3442
First of all, remove that print '******...'
line. It just confuses everyone. Instead, let's try this code...
首先,删除该print '******...'
行。只会让大家感到困惑。相反,让我们试试这个代码......
import os
import time
for i in range(2):
print("I'm about to be a dad!")
time.sleep(5)
pid = os.fork()
if pid == 0:
print("I'm {}, a newborn that knows to write to the terminal!".format(os.getpid()))
else:
print("I'm the dad of {}, and he knows to use the terminal!".format(pid))
os.waitpid(pid, 0)
Okay, first of all, what is "fork"? Forkis a feature of modern and standard-compliant operating systems (except of M$ Windows: that joke of an OS is all but modern and standard-compliant) that allows a process (a.k.a: "program", and that includes the Python interpreter!) to literally make an exact duplicate of itself, effectively creating a new process (another instance of the "program"). Once that magic is done, both processes are independent. Changing anything in one of them does not affect the other one.
好的,首先,什么是“fork”?Fork是现代且符合标准的操作系统(M$ Windows 除外:操作系统的笑话几乎是现代且符合标准的)的一个功能,它允许一个进程(又名:“程序”,包括 Python 解释器) !) 从字面上复制自身,有效地创建一个新进程(“程序”的另一个实例)。一旦魔法完成,两个过程都是独立的。更改其中一个中的任何内容不会影响另一个。
The process responsible for spelling out this dark and ancient incantation is known as the parent process. The soulless result of this immoral abomination towards life itself is known as the child process.
负责拼出这个黑暗而古老的咒语的过程被称为父过程。这种对生命本身的不道德憎恶的无灵魂结果被称为儿童过程。
As shall be obvious to all, including those for which it isn't, you can become a member of that select group of programmers who have sold their soul by means of os.fork()
. This function performs a fork operation, and thus results in a second process being created out of thin air.
众所周知,包括那些不为之的人,您可以成为通过os.fork()
. 该函数执行分叉操作,从而导致无中生有地创建第二个进程。
Now, what does this function return, or more importantly, howdoes it even return? If you want not to become insane, pleasedon't go and read the Linux kernel's /kernel/fork.c
file! Once the kernel does what we know it has to do, but we don't want to accept it, os.fork()
returns in the twoprocesses! Yes, even the call stack is copied on!
现在,这个函数返回什么,或者更重要的是,它是如何返回的?如果你不想发疯,请不要去阅读Linux内核的/kernel/fork.c
文件!一旦内核做了我们知道它必须做的事情,但我们不想接受它,os.fork()
在两个进程中返回!是的,甚至调用堆栈也被复制了!
So, if they are exact copies, how does one differentiate between parent and child? Simple. If the result of os.fork()
is zero, then you're working in the child. Otherwise, you're working in the parent, and the return value is the PID (Process IDentifier) of the child. Anyway, the child can get its own PID from os.getpid()
, no?
那么,如果它们是精确的副本,那么如何区分父母和孩子呢?简单的。如果 的结果os.fork()
为零,那么您正在处理子项。否则,您在父级中工作,返回值是子级的 PID(进程标识符)。无论如何,孩子可以从 获得自己的PID os.getpid()
,不是吗?
Now, taking this into account, and the fact that doing fork()
inside a loop is the recipe for mess, this is what happens. Let's call the original process the "master" process...
现在,考虑到这一点,以及在fork()
循环内进行操作会导致混乱的事实,这就是会发生的情况。让我们称原始进程为“主”进程......
- Master:
i = 0
, forks into child-#1-of-master- Child-#1-of-master:
i = 1
forks into child-#1-of-child-#1-of-master - Child-#1-of-child-#1-of-master:
for
loop over, exits - Child-#1-of-master:
for
loop over, exits
- Child-#1-of-master:
- Master:
i = 1
, forks into child-#2-of-master- Child-#2-of-master:
i = 1
forks into child-#1-of-child-#2-of-master - Child-#1-of-child-#2-of-master:
for
loop over, exits - Child-#2-of-master:
for
loop over, exits
- Child-#2-of-master:
- Master:
for
loop over, exits
- Master:
i = 0
, 分叉到 child-#1-of-master- Child-#1-of-master:
i = 1
分叉到 child-#1-of-child-#1-of-master - Child-#1-of-child-#1-of-master:
for
循环,退出 - Child-#1-of-master:
for
循环,退出
- Child-#1-of-master:
- Master:
i = 1
, 分叉到 child-#2-of-master- Child-#2-of-master:
i = 1
分叉到 child-#1-of-child-#2-of-master - Child-#1-of-child-#2-of-master:
for
循环,退出 - Child-#2-of-master:
for
循环,退出
- Child-#2-of-master:
- Master:
for
循环,退出
As you can see, there are a total of 6 parent/child prints coming from 4 unique processes, resulting in 6 lines of output, something like...
如您所见,共有来自 4 个独特进程的 6 个父/子打印,从而产生 6 行输出,类似于...
I'm the dad of 12120, and he knows to use the terminal!
I'm 12120, a newborn that knows to write to the terminal!
I'm the dad of 12121, and he knows to use the terminal!
I'm 12121, a newborn that knows to write to the terminal!
I'm the dad of 12122, and he knows to use the terminal!
I'm 12122, a newborn that knows to write to the terminal!
我是12120的爸爸,他知道使用终端!
我是12120,一个会写终端的新生儿!
我是12121的爸爸,他知道使用终端!
我是12121,一个会写终端的新生儿!
我是12122的爸爸,他知道使用终端!
我是12122,一个会写终端的新生儿!
But that's just arbitrary, it could have output this out instead...
但这只是任意的,它可以输出它来代替......
I'm 12120, a newborn that knows to write to the terminal!
I'm the dad of 12120, and he knows to use the terminal!
I'm 12121, a newborn that knows to write to the terminal!
I'm the dad of 12121, and he knows to use the terminal!
I'm 12122, a newborn that knows to write to the terminal!
I'm the dad of 12122, and he knows to use the terminal!
我是12120,一个会写终端的新生儿!
我是12120的爸爸,他知道使用终端!
我是12121,一个会写终端的新生儿!
我是12121的爸爸,他知道使用终端!
我是12122,一个会写终端的新生儿!
我是12122的爸爸,他知道使用终端!
Or anything other than that. The OS (and your motherboard's funky clocks) is solely responsible for the order in which processes get timeslices, so go blame on Torvalds (and expect no self-steem when back)if you dislike how the kernel manages to organize your processes ;).
或者除此之外的任何东西。操作系统(和你主板的时髦时钟)全权负责进程获得时间片的顺序,所以如果你不喜欢内核管理你的进程的方式,那就去责怪 Torvalds(并期望在返回时没有自我控制);)。
I hope this has led some light on you!
我希望这对你有所启发!