python中多进程的相关技术
--如何创建的子线程。
self.pid = os.fork()
if self.pid == 0:
code = process_obj._bootstrap()
sys.stdout.flush()
sys.stderr.flush()
os._exit(code)
os fork 创建了一个新的进程,该子进程和父进程唯一不同的就是Pid,父id的pid不为空,所以从这个判断条件开始两个进程已经开始
执行不同的代码。
其中_bootstrap函数,做了几件事情,初始化子进程的上下文环境,以及执行相应的函数,这段代码在process。run()函数中,和C的非常相似。
由于子进程是父进程的复制,所以按道理说,在执行完上述的代码后,应该会返回到主函数,因为父进程是这么干的。
但是由于在分支的代码块中,有一个exit的函数,所以就退出了,不会再返回主进程去跑父进程的代码块
--父线程如何监控子进程的状态
在主进程中,在创建了子进程之后,
有段代码如下:_current_process._children.add(self),会将刚创建的子进程添加到_children的列表里面,这样的话,父进程就维系了和子进程的关系。
并且将子进程的所有信息都放置在_children里面。
python的process的join是父进程在等待子进程结束的信息。如果子进程结束的话,
Process.join() 调用 Popen.wait(),而 wait() 内部则通过 poll() 调用 os.waitpid() 等待子进程终止。
每个子进程在执行完成后,都会有:util._exit_function(),先将子进程的子进程给清理干净。最后返回return exitcode
--子进程异常结束,父进程如何处理。
如果子进程运行异常,抛出了个异常,或者在进程的具体代码模块的执行中遇到了exit(0)的,父进程会捕获这些异常,并且正确返回。
子进程代码中如果return 或者没有返回,都是ok的。
子进程代码中如果有exit(-1),也是可以正常退出的。也是可以正常的把错误的输出和,正常的输出转向到控制台。
子进程代码中如果有跑出异常,那么也是可以将所有的信息输出。
子进程如果被异常终止了,那么该进程会属于正常终止,所有没有保存到磁盘的信息都会被丢失,父进程能够收到该子进程正常结束的消息,能够正常终止。
所以子进程中无论发生了什么,都会正常的返回,除非其中某个语句卡住了。
--如果子进程卡住了,那么父进程能做什么
正常情况下,子进程应该不会卡住的,但是比如读hdfs的文件,或者调用对方的http请求,都会出现卡住的情况。
那么我们尽量被保证不会这样的情况,都会设置timeout的时间。
一旦卡住,那么直接调用terminate ,那么就会出现僵尸进程。
dwdev 28346 28345 0 21:56 pts/0 00:00:00 [python] <defunct>
dwdev 28347 28345 0 21:56 pts/0 00:00:00 [python] <defunct>
这种情况一般是由于子进程的退出的时候,进程内部有些信息没有被处理完。
a=Queue()
b=Array('i',range(10))
for i in threadLen:
t=Process(target=worker,args=(a,b))
threads.append(t)
for i in threadLen:
threads[i].start()
for i in threadLen:
threads[i].terminate()
print "i is:"+str(i)
# threads[i].join()
print a.get()#在这里的时候卡住了。。
print b[0]
print b[1]
如果改成下面的形式,那么就可以自然退出。
t=Process(target=worker,args=(str(i)))
threads.append(t)
for i in threadLen:
threads[i].start()
for i in threadLen:
threads[i].terminate()
print "i is:"+str(i)
# threads[i].join()
print "finished"
这样就可以自然退出,
前面这个例子和后面这个例子,经过多次的测试,发现问题是由于queue这个对象造成的,
queue的对象中的get方法,当queue中没有对象的时候,那么就会卡住主进程,而此时子进程已经结束了,没有join的函数处理进程终止的信息。
导致子进程都变成僵尸进程。
如果在terminate之后,加了join的函数,那么就没有defunct的存在了。这个defunt就是子进程的信号没有被及时处理,导致子进程无法正常退出。
http://www.erlangsir.com/2011/04/22/python-library-multiprocessing/