专栏首页python3python之多进程fork

python之多进程fork

一:多进程概念

 python中实现多进程是通过os.fork()这个函数来实现,这个函数和操纵系统本身结合的非常紧密,windows下就无法使用os.fork()这个函数。python中的os.fork()被调用后就会立即生成一个子进程,是通过copy父进程的地址空间和资源来实现子进程的创建,同时这个函数在子进程中返回的是0,在父进程中返回的是子进程的PID。子进程在结束父进程还未结束的时候,子进程这段时间是处于Zombie状态,可以通过ps命令查看到进程的状态,Zombie的目的是为了在子进程结束的时候可以保存一些结束信息供父进程来收集。

二:多进程的简单实现

#!/usr/bin/env python
import os
def task(id):
        print "work %d" %id
pid = os.fork()
if pid == 0:
        print "I am a child"
        task(1)
else:
        print "I am father child"

执行结果如下:
I am father child
I am a child
work 1

多次执行上面的例子可能结果的顺序会不一样,子进程和父进程执行的顺序是无法预估的。

os.fork()执行后父进程继续往下执行,子进程也会从os.fork()语句之后开始运行,并且子进程拥有父进程所有的变量,但是两者是独立的。

#!/usr/bin/env python
import os
import time
def task(id):
        print "work %d" %id
var = 10
pid = os.fork()
if pid == 0:
        print "I am a child"
        var = 9
        task(1)
else:
        print "I am father child"
        time.sleep(3)
        print var
结果是:
I am father child
I am a child
work 1
10

上面这段代码演示了子进程和父进程的var这个变量是独立,在子进程中改变了var变量的值,并不影响父进程中的var变量值,两者是独立的,为了防止父进程先执行,子进程后执行,所以让父进程sleep(3)了一会再输出var的值。子进程结束后,但是父进程还没有结束的时候,子进程是出于Zombie状态的,这个需要父进程去收集子进程的信息释放子进程。如果父进程结束了子进程没有结束,那么子进程就会寄托给pid为1的进程来管理。

#!/usr/bin/env python
import os
import time
pid = os.fork()
if pid == 0:
        print "I am a child %d" %os.getpid()
else:
        time.sleep(100)
        print "done"
输出信息:
I am a child 57786
一直处于等待状态......
done
在处于等待状态的时候立刻使用ps命令查看子进程的状态
[root@localhost ~]# ps ax|grep 57786
57786 pts/4    Z+     0:00 [python] <defunct>
57792 pts/5    S+     0:00 grep 57786
通过上面的状态发现子进程处于defunct这个状态就是Zombie状态。

三:多进程处理Zombie方式一

对于处理Zimbie状态的子进程有两种方式,第一种是基于信号的处理,子进程在结束后就会发出SIGCHLD这个信号,通过singal接收到这个信号就可以进行收集了。

#!/usr/bin/env python
import os,time,signal
def chldhandler(signum,stackframe):
        while 1:
                try:
                        result = os.waitpid(-1,os.WNOHANG)
                except:
                        break
                print "Reaped child process %d" % result[0]
        signal.signal(signal.SIGCHLD,chldhandler)

signal.signal(signal.SIGCHLD,chldhandler)
print "Before the fork my PID is",os.getpid()

pid = os.fork()
if pid:
        print "hello from the parent the child will be PID %d" %pid
        print "Sleeping 10 sconds....."
        time.sleep(1000)
        print "sleep done"
else:
        print "Child sleeping 5 seconds"
        time.sleep(5)
执行结果:
Before the fork my PID is 58322
hello from the parent the child will be PID 58323
Sleeping 10 sconds.....
Child sleeping 5 seconds
Reaped child process 58323
sleep done
5秒过后子进程结束出发信号处理函数,对子进程进行了收集和处理。并且信号打断了父进程的sleep

singal是一个信号量函数,chldhandlr是一个自定义的的信号处理的handler,通过singal可以注册接收到什么信号就自动触发哪个handler

waitpid的第一个参数代表等待所有的子进程终止,第二个参数代表如果没有已经终止的子进程就立即返回。waitpid的返回结果是一个进程的PID和退出信息组成的一个元组。在while循环结束后又重新注册了信号处理函数这是因为有些unix在信号处理程序结束后就失效了,无法再次处理其他子进程,

四:多进程处理Zombie方式二

第二中处理Zombie进程的方式是轮训,父进程一段时间就去收集一下子进程,释放Zombie进行。

#!/usr/bin/env python
import os,time
def reap():
        while 1:
                try:
                        result = os.waitpid(-1,os.WNOHANG)
                except:
                        break
                print "Reaped child process %d" % result[0]
        print "Before the fork,my PID is",os.getpid()
pid = os.fork()
if pid:
        print "Hello from the parent .The child will be PID %d" % pid
        print "Parent sleeping 60 seconds"
        time.sleep(60)
        print "Parent sleep done"
        reap()
        print "Parent sleeping 60 seconds"
        time.sleep(60)
        print "Parent sleep done"
else:
        print "Child sleeping 5 seconds..."
        time.sleep(5)
        print "Child terminating"

执行结果:
Parent sleeping 60 seconds
Child sleeping 5 seconds...
#等待5秒.......
Child terminating
#子进程结束了
#等待55秒父进程睡眠结束
Parent sleep done
#启动reap()去采集子进程的信息,释放子进程
Reaped child process 58595
Before the fork,my PID is 58594
Parent sleeping 60 seconds
Parent sleep done

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python3内置函数大全

    由于面试的时候有时候会问到python的几个基本内置函数,由于记不太清,就比较难受,于是呕心沥血总结了一下python3的基本内置函数

    py3study
  • python11.23

    2.第二个改进要求:程序应该提供多次机会给用户猜测,专业点来说就是程序需要重复运行某些代码。

    py3study
  • Python基础知识(一)

    py3study
  • 电话面试题总结,Python基础部分

    用户4945346
  • python 基础知识第10讲:函数的初识、参数、解包

    函数也是一个对象,就是我们在内存当中所开辟的一块区域,通过一些代码块实现特定的功能 。 可以用来保存一些可执行的代码,并且可以在需要的时候,对这些代码(语句)...

    小海怪的互联网
  • 匿名函数,内置函数,闭包

    练习: def func(a,b): return a + b print(func(4,5)) # 构建匿名函数 func1 = lambda ...

    py3study
  • python列表、元组、字典、集合的简单

    py3study
  • 【python入门系列课程 第十二课 字符串和列表进阶】

    本系列课程是针对无基础的,争取用简单明了的语言来讲解,学习前需要具备基本的电脑操作能力,准备一个已安装python环境的电脑。如果觉得好可以分享转发,有问题的地...

    用户7054460
  • Python 三十大实践、建议和技巧

    【导读】2020年,你又立了什么新的 Flag?新一年,我们先为大家准备 30 个非常优秀的 Python 实践技巧。希望这些诀窍能在实际工作中帮助大家,并且学...

    AI科技大本营
  • Python3 基础语法教程

    编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码:

    py3study

扫码关注云+社区

领取腾讯云代金券