了解这个“分叉”脚本的流程

时间:2018-05-30 20:08:45

标签: python fork

我有这个代码,为了更好地理解它,我添加了一条线来跟踪pid等于零的位置:

import os, time
def counter(count): # run in new process
    for i in range(count):
        time.sleep(0.00001) # simulate real work
        print('[%s] => %s' % (os.getpid(), i))

for i in range(5):

    pid = os.fork()
    print("The pid is: ", pid)# the one I added
    if pid != 0:
        print('Process %d spawned' % pid) # in parent: continue
    else:
        counter(5) # else in child/new process
        os._exit(0) # run function and exit
print('Main process exiting.')

问题:

1)什么激活了对抗的呼叫?检查他们的pid的新进程是否等于零,然后调用计数器?

2)如果我将睡眠时间更改为1秒(而不是十分之一密耳),则不会打印子进程的数据。然后在后台发生了什么?

我得到了这个结果:

the pid is:  6                                                                                                                                                                     
Prociss 6 spawned                                                                                                                                                                 
the pid is:  7                                                                                                                                                                     
Prociss 7 spawned                                                                                                                                                                 
the pid is:  8                                                                                                                                                                     
Prociss 8 spawned                                                                                                                                                                 
the pid is:  9                                                                                                                                                                     
Prociss 9 spawned                                                                                                                                                                 
the pid is:  10                                                                                                                                                                    
Prociss 10 spawned                                                                                                                                                                
Main prociss exiting.                                                                                                                                                             
the pid is:  0                                                                                                                                                                     
the pid is:  0                                                                                                                                                                     
the pid is:  0                                                                                                                                                                     
the pid is:  0                                                                                                                                                                     
[6] => 0                                                                                                                                                                          
[8] => 0                                                                                                                                                                          
[7] => 0                                                                                                                                                                          
[6] => 1                                                                                                                                                                          
the pid is:  0                                                                                                                                                                     
[8] => 1                                                                                                                                                                          
[6] => 2                                                                                                                                                                          
[7] => 1                                                                                                                                                                          
[9] => 0                                                                                                                                                                          
[6] => 3                                                                                                                                                                          
[8] => 2                                                                                                                                                                          
[7] => 2                                                                                                                                                                          
[9] => 1                                                                                                                                                                          
[8] => 3                                                                                                                                                                          
[6] => 4                                                                                                                                                                          
[7] => 3                                                                                                                                                                          
[8] => 4                                                                                                                                                                          
[7] => 4                                                                                                                                                                          
[9] => 2                                                                                                                                                                          
[10] => 0                                                                                                                                                                         
[9] => 3                                                                                                                                                                          
[10] => 1                                                                                                                                                                         
[9] => 4                                                                                                                                                                          
[10] => 2                                                                                                                                                                         
[10] => 3                                                                                                                                                                         
[10] => 4                                                                                                                                                                         


...Program finished with exit code 0   

1 个答案:

答案 0 :(得分:0)

回答你的两个问题:

  是什么激活了反击的召唤?检查他们的pid的新进程是否等于零,然后调用计数器?

是。 os.fork()是一种不同寻常的野兽,因为它“违反了物理定律”:它在两个独立的过程中返回两次。这两个进程(几乎)相同,所以方式知道你是哪一个(父或子)是看{4}}返回的内容:如果它返回零,你是孩子,否则返回值是孩子的pid。

由于两个进程都执行os.fork()行,因此pid 为零的那一行(即子进程)将执行if pid != 0块,该块将调用{ {1}}。

  

如果我将睡眠时间更改为1秒(而不是十分之一密耳),则不会打印子进程的数据。然后在后台发生了什么?

你不是else为了你的孩子。这意味着一旦父进程退出,它就会“孤立”其所有子进程。 counter将有助于采用它们,但是在此过程中它们可能会失去对其控制终端的访问权限,仅此一项就足以杀死它们。此外,在现代Linux系统上,wait可能会杀死孩子,如果你没有告诉他们。

通常,如果您使用的是init,则还需要systemd。父级获取分叉的子级的pid,以便它可以在该pid上调用fork。这有两个目的:第一,它实际上等待孩子完成执行,其次它将允许父母从孩子那里接收退出代码,这将让你知道孩子是否成功退出或者是否被杀死。如果您还没等,那就没有100%可靠的方法来了解孩子的遭遇。 (即使你把pid存放在其他地方,也有可能在你有机会再次检查之前重新使用pid。)

wait /(wait)/ fork的舞蹈中有许多细微之处;它们的简洁性非常优雅,但是如果你正在触摸这些工具,那么它就会有很多的假设知识。如果您没有阅读任何教程,请不要期望能够有效地使用exec。如果你不想成为Unix过程模型的专家(以及信号处理,控制终端和会话领导等等),那么你最好使用更高级别的抽象来解决问题而不是而不是像这样的低级别的东西。 Python有助于提供wait模块来帮助解决这个问题,这是一个更好的通用工具。