zoukankan      html  css  js  c++  java
  • 多进程和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开发者的常规想法. 当然任何诡异的现象, 背后一定有迹可循.

    写在最后:
      
    如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

       

  • 相关阅读:
    eclipse中的Invalid text string (xxx).
    在jsp文件中出现Unknown tag (c:out)
    eclipse 界面复原
    ecilpse 纠错插件
    Multiple annotations found at this line:- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
    Port 8080 required by Tomcat v9.0 Server at localhost is already in use. The server may already be running in another process, or a system process may be using the port.
    调用第三方https接口
    调用第三方http接口
    创建带值枚举
    spring整合redis之Redis配置文件
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/4527680.html
Copyright © 2011-2022 走看看