前言:
  最近帮朋友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. URAL 1519 基础插头DP

    题目大意: 给定一个图,一部分点'*'作为障碍物,求经过所有非障碍点的汉密尔顿回路有多少条 基础的插头DP题目,对于陈丹琦的论文来说我觉得http://blog.sina.com.cn/s/blog_ ...

  2. Rhel6-lanmp架构配置文档

    l--操作系统:windows  linux  unix  mac OS a--网页发布软件:apache nginx iis m--数据库:mysql  pgsql  oracle... p--网页 ...

  3. Java注解配置

    Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annota ...

  4. OpenCV之响应鼠标(二):函数cvSetMouseCallback()和其副程式onMouse()的使用(OpenCV2.4.5)

    每當滑鼠在視訊視窗介面點擊一下的時候,都會有固定三個動作 1.點擊(Click) 2.放開(Down)3.滑動(move) 因此,程式執行滑鼠在點擊的時候onMouse()都會連續跑三次,代表滑鼠在點 ...

  5. [Windows驱动]流媒体驱动开发

    从Windows98开始,Windows流媒体驱动遵循Windows Driver Model(WDM)模型并使用Kernel Streaming(KS)组件.Kernel Streaming(KS) ...

  6. IOS打开其他应用、以及被其他应用打开

    1.打开其他应用 appURLStr = "cwork://app_id?title=xxx&content=xxx" [[UIApplication sharedAppl ...

  7. uitabbarcontroller中 在设置tab bar item的image属性后不显示问题

    开始使用ios中的UITabBarController,在给Tab Bar Item设置自定义图片的时候,遇到了问题 按照如下配置: 出来的结果确是: 实际上test24.png应该是: 纠结了很久, ...

  8. 毕向东day23--java基础-网络总结

    传输层:TCP/UDP   UDP例如:qq聊天,录屏软件,桌面共享     TCP建立链接:三次握手,例如,我叫你一声老王(一次),老王回答说:到.(二次),我对老王说,我知道你到了.(三次握手)! ...

  9. spring六种种依赖注入方式

    平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...

  10. Ubuntu 14.10 下NodeJS Cannot find module 'npmlog'

    在安装brunch的时候npm install -g brunch发现如下问题: Error: Cannot find module ‘npmlog’ at Function.Module._reso ...