前言:
  最近帮朋友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清理函数的更多相关文章

  1. POSIX 线程清理函数

    POSIX 多线程的 cleanup 函数 控制清理函数的函数有两个,一个是 pthread_cleanup_push(), 用来把清理函数压入栈中,另一个是 pthread_cleanup_pop( ...

  2. linux清理函数

    每个非试验性的模块也要求有一个清理函数, 它注销接口, 在模块被去除之前返回所有资 源给系统. 这个函数定义为: static void   exit cleanup_function(void) { ...

  3. C/C++网络编程7——多进程服务器端之fork函数

    通过前面几节的内容,我们已经可以实现基本的C/S结构的程序了,但是当多个客户端同时向服务器端请求服务时,服务器端只能按顺序一个一个的服务,这种情况下,客户端的用户是无法忍受的.所以虚实现并发的服务器端 ...

  4. Linux下多进程编程之exec函数语法及使用实例

    exec函数族 1)exec函数族说明 fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容,但是,这个新创建的进程如何执行呢?exec函数族就提供了一个在进程中启动另一个程序执行的 ...

  5. 深入浅出--UNIX多进程编程之fork()函数

    0前言 上周都在看都在学习unix环境高级编程的第八章--进程控制.也就是这一章中.让我理解了unix中一些进程的原理.以下我就主要依照进程中最重要的三个函数来进行解说.让大家通过阅读这一篇文章彻底明 ...

  6. 多进程编程之system()函数

    1.system函数: 使用函数system,在程序中执行一个shell命令字符串很方便.它是一个和操作系统紧密相关的函数,用户可以使用它在自己的程序中调用系统提供的各种命令,执行系统的命令行,其实也 ...

  7. Creo二次开发--内存清理函数

    我们在处理模型文件时,总会遇到内存环境的清除问题.一个干净的Creo工作环境.是保证工作能顺利完毕的保障. ProMdlEraseNotDisplayed()函数提供了清除未显示模型的功能. 当须要循 ...

  8. atexit注册的函数是在main函数之后执行?

    跟atexit函数相识已久,man手册里对atexit的解释是这么一段: The atexit() function registers the given function to be called ...

  9. 回收进程用户空间资源 exit()函数 _exit()函数 atexit()函数 on_exit()函数

    摘要:本文主要讲述进程的终止方式,以及怎样使用exit()函数来终止进程.回收进程用户空间资源:分析了exit()函数与_exit()函数,returnkeyword的差异.同一时候具体解读了怎样使用 ...

随机推荐

  1. uva -- 10766

    一开始我感觉是模板题  是不想写的 后来发现我的模板上没有 就敲了一遍 可以忽略这句屁话     在信息学竞赛中,有关生成树的最优化问题如最小生成树等是我们经常遇到的,而对生成树的计数及其相关问题则少 ...

  2. [Js]面向对象基础

    一.什么是对象 对象是一个整体,对对外提供一些操作 二.什么是面向对象 使用对象时,只关注对象提供的功能,不关注其内部细节,比如Jquery 三.Js中面向对象的特点 1.抽象:抓住核心问题 2.封装 ...

  3. bzoj 1791: [Ioi2008]Island 岛屿

    #include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...

  4. 北邮新生排位赛1解题报告a-c

    <div class="page-header" style="padding-bottom: 9px; margin: 20px 0px 30px; border ...

  5. php 加密解密字符串

    /********************************************************************* 函数名称:encrypt 函数作用:加密解密字符串 使用方 ...

  6. 神奇的NOIP模拟赛 T3 LGTB 玩THD

    LGTB 玩THD LGTB 最近在玩一个类似DOTA 的游戏名叫THD有一天他在守一座塔,对面的N 个小兵排成一列从近到远站在塔前面每个小兵有一定的血量hi,杀死后有一定的金钱gi每一秒,他都可以攻 ...

  7. K2 BPM + SAP,实现全方面管理企业

    K2作为专业的BPM.工作流管理平台供应商,面向庞大的SAP用户群体,除了提供产品化的SAP集成工具「K2 connect」产品之外,更拥有一套得到众多客户验证的集成解决方案. 此方案可供SAP用户或 ...

  8. Android的R.java文件

    1.Android资源管理简介: Android应用程序资源可以分为两大类,分别放在assets和res文件夹下.assets目录下保存的是一些原始的文件,可以以任何方式来进行组织.这些文件最终会被原 ...

  9. SharePoint 2016 的新特性概览(二)(What's New for IT Professionals in SharePoint Server 2016)

    博客地址:http://blog.csdn.net/FoxDave SharePoint 2016 的新特性 三. 监测和数据(Insights and Data) 实时数据监测,包括对使用情况.存储 ...

  10. 跨域请求之jQuery的ajax jsonp的使用解惑

    前天在项目中写的一个ajax jsonp的使用,出现了问题:可以成功获得请求结果,但没有执行success方法,直接执行了error方法提示错误——ajax jsonp之前并没有用过,对其的理解为跟普 ...