多进程和atexit清理函数
前言:
最近帮朋友review其模块服务代码, 使用的是python的twisted网络框架. 鉴于之前并没有使用过, 于是决定好好研究一番.
不过这个问题, 和twisted网络框架本身没有关系, 而是为了提升QPS性能, 引入了多进程模型而遇到的一个奇怪问题.
本文将讲述python的多进程机制, 以及atexit的清理函数机制. 权作python的学习笔记.
场景构造:
具体的业务代码可以简化为如下所述:
父进程开启多个常驻子进程后, 安然"退休"并结束运行.
进程的创建借助multiprocessing模块来实现, 其使用方式如thread管理接口相仿.
编辑python代码文件 subproc_sample.py:
#! /usr/bin/python
#-*- coding: UTF-8 -*- import time
import multiprocessing # 子进程业务逻辑
def proc_func():
while True:
time.sleep(1) if __name__ == "__main__":
# 创建4个子进程
for i in range(4):
# 创建子进程并启动
p = multiprocessing.Process(target=proc_func, args=())
p.start()
# 父进程安然退出
该样例中, 父进程创建4个子进程后, 就Do nothing, 安然退出了(预期中).
然后事实却不如此, 我们借助 ps 命令过滤后发现, 父进程和4个子进程都活着, 如下图所示:

这中间有何玄机呢? 父进程为何不按常理出牌呢?
问题追踪:
"工欲善其事, 必先利其器", 我们借助pstack来查看下父进程(python底层是用c/c++编写)为何不退出.
命令: pstack <pid>, pid为父进程id.
从堆栈的顶层可以看到, 父进程阻塞在waitpid系统调用. 看来父进程在等待子进程的正常退出.
令一方面, 从堆栈中, 我们可以发现, 此时父进程已在python主程序退出之后, 其做了清理工作Py_Finalize.
这让我们联想到unix c中提到atexit退出清理机制.
python是否也有类似的机制, 可以注册程序的退出清理函数.
我们把父进程切换到前台运行, fg之后, ctrl+c挂掉父进程.

从中可以看到atexit.py, 由此可见, 我们的猜测并没有错.

在/usr/lib64/python2.6/multiprocessing/util.py中, 我们可以找到注册的时间点, 还有注册的函数_exit_function, 该函数完成了父进程对子进程的wait操作.

总结:
python的多线程设计的非常的巧妙, 使得创建/使用多进程,如同多线程使用那样方便和简洁. 当然python背后也封装添加了一些额外的工作, 这些工作可能会有悖于Unix开发者的常规想法. 当然任何诡异的现象, 背后一定有迹可循.
写在最后:
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

多进程和atexit清理函数的更多相关文章
- POSIX 线程清理函数
POSIX 多线程的 cleanup 函数 控制清理函数的函数有两个,一个是 pthread_cleanup_push(), 用来把清理函数压入栈中,另一个是 pthread_cleanup_pop( ...
- linux清理函数
每个非试验性的模块也要求有一个清理函数, 它注销接口, 在模块被去除之前返回所有资 源给系统. 这个函数定义为: static void exit cleanup_function(void) { ...
- C/C++网络编程7——多进程服务器端之fork函数
通过前面几节的内容,我们已经可以实现基本的C/S结构的程序了,但是当多个客户端同时向服务器端请求服务时,服务器端只能按顺序一个一个的服务,这种情况下,客户端的用户是无法忍受的.所以虚实现并发的服务器端 ...
- Linux下多进程编程之exec函数语法及使用实例
exec函数族 1)exec函数族说明 fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容,但是,这个新创建的进程如何执行呢?exec函数族就提供了一个在进程中启动另一个程序执行的 ...
- 深入浅出--UNIX多进程编程之fork()函数
0前言 上周都在看都在学习unix环境高级编程的第八章--进程控制.也就是这一章中.让我理解了unix中一些进程的原理.以下我就主要依照进程中最重要的三个函数来进行解说.让大家通过阅读这一篇文章彻底明 ...
- 多进程编程之system()函数
1.system函数: 使用函数system,在程序中执行一个shell命令字符串很方便.它是一个和操作系统紧密相关的函数,用户可以使用它在自己的程序中调用系统提供的各种命令,执行系统的命令行,其实也 ...
- Creo二次开发--内存清理函数
我们在处理模型文件时,总会遇到内存环境的清除问题.一个干净的Creo工作环境.是保证工作能顺利完毕的保障. ProMdlEraseNotDisplayed()函数提供了清除未显示模型的功能. 当须要循 ...
- atexit注册的函数是在main函数之后执行?
跟atexit函数相识已久,man手册里对atexit的解释是这么一段: The atexit() function registers the given function to be called ...
- 回收进程用户空间资源 exit()函数 _exit()函数 atexit()函数 on_exit()函数
摘要:本文主要讲述进程的终止方式,以及怎样使用exit()函数来终止进程.回收进程用户空间资源:分析了exit()函数与_exit()函数,returnkeyword的差异.同一时候具体解读了怎样使用 ...
随机推荐
- python中的urlencode与urldecode
当url地址含有中文,或者参数有中文的时候,这个算是很正常了,但是把这样的url作为参数传递的时候(最常见的callback),需要把一些中文甚至'/'做一下编码转换. 所以对于一些中文或者字符,ur ...
- 解析网络json数据,模拟美团界面显示。
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android=&q ...
- POJ 1012 Joseph 推导,暴力,约瑟夫环,打表 难度:2
http://poj.org/problem?id=1012 答案以954ms飘过,不过这道题可以轻松用打表过 思路:如果我们把每个人位于数组中的原始编号记为绝对编号,每次循环过后相对于绝对编号为0的 ...
- HDU 4405 Aeroplane chess 概率DP 难度:0
http://acm.hdu.edu.cn/showproblem.php?pid=4405 明显,有飞机的时候不需要考虑骰子,一定是乘飞机更优 设E[i]为分数为i时还需要走的步数期望,j为某个可能 ...
- LCA-倍增法(在线)
原文:http://www.tuicool.com/articles/N7jQV32 1. DFS预处理出所有节点的深度和父节点 inline void dfs(int u) { int i; for ...
- 一模 (5) day1
第一题: 题目大意:求出1-10^n 这些数中,包含数字3的有多少个. n<=1000: 解题过程: 1.这题一看就是高精度+递推..如果n=1000,那么假设个位是3,其他999位任意..那么 ...
- php base64_decode 解码方法
<?php header('Content-Type:text/html;charset=utf-8'); function encode_file_contents($filename) { ...
- node cheerio
所谓工欲善其事,必先利其器,所以通读了cheerio的API,顺便翻译了一遍,有些地方因为知道的比较少,不知道什么意思,保留了英文,希望各位不吝告诉我,然后一起把这个翻译完成. ###cheerio ...
- Java中的深拷贝和浅拷贝
1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...
- 构建者模式(Builder)示例代码
package com.test; /** * Created by xiaonanhai on 2015/5/30. */ public class Builder { private String ...