僵尸与孤儿进程

僵尸进程:父进程的子进程结束的时候父进程没有wait()情况下子进程会变成僵尸进程

孤儿进程(无害)

一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

情况1 无害

父进等着子进程都死,回收僵尸进程。

情况2 无害

父进程死了,子进程活着,都要被init进程接管并且回收。

情况3 有害

父进程一直不死,造成了大量僵尸进程。占用了大量的pid号

pid号是有限的。

解决方案:

最直接的办法就是杀死父进程 。

Process用法

之前我们简单介绍了如何用Process实现简单的多线程

join的用法

join 的作用主要是阻塞住主进程再等待子进程结束,然后再往下执行,(了解的是:内部会待用wait())

join的写法和start类似,一般用于start之后

from multiprocessing import Process
import time
def foo():
print('进程 start ')
time.sleep(2.3)
print('进程 end ') if __name__ == '__main__':
p = Process(target=foo)
p.start() #
# 核心需求就是
# time.sleep(5)
p.join() # 阻塞住主进程再等待子进程结束,然后再往下执行,(了解的是:内部会待用wait())
print('主')

join的多进程用法

如果不止一个进程的话,join又会被如何使用呢

from multiprocessing import Process
import time
def foo(x):
print('进程 start ')
time.sleep(x)
print('进程 end ') if __name__ == '__main__':
p1 = Process(target=foo,args=(1,))
p2 = Process(target=foo,args=(2,))
p3 = Process(target=foo,args=(3,))
start = time.time()
p1.start() #
p2.start() #
p3.start() #
# 核心需求就是
# time.sleep(5)
p3.join() #1s
p1.join() #1s
p2.join() #1s
# 总时长:按照最长的时间计算多一点。
end = time.time()
print(end-start) #3s多 or 6s多 ? 正解:3s多
print('主')

在这种用法中,我们使用了三个进程。我们先将三个进程都启动,随后再同时join。我们会发现最后的结果是3秒多一点。其实这三个进程是同时开始的,当第一个进程结束的时候,第二个和第三个进程已经开始一秒多了,所以最后的结果是3秒多

当然,如果我们一个一个的start然后join也是可以达成串行的结果:

from multiprocessing import Process
import time
def foo(x):
print(f'进程{x} start ')
time.sleep(x)
print(f'进程{x} end ') if __name__ == '__main__':
p1 = Process(target=foo,args=(1,))
p2 = Process(target=foo,args=(2,))
p3 = Process(target=foo,args=(3,))
start = time.time()
p1.start() #
p1.join() #
p2.start() #
p2.join() #
p3.start() #
p3.join() #
# 不如不开,直接穿行调用函数反而快
# foo(1)
# foo(2)
# foo(3)
end = time.time()
print(end-start)
print('主')

只不过这样的总时长反而高于串行,而且代码冗余,没有什么意义

join的多线程用法优化

不知道各位看官有没有觉得之前的进程每个都要写一个start和join,看上去很麻烦吗?如果三个进程还可以接受,那如果更多的进程呢?我们可以依次利用循环对其进行优化

from multiprocessing import Process
import time
def foo(x):
print(f'进程{x} start ')
time.sleep(x)
print(f'进程{x} end ') if __name__ == '__main__':
start = time.time()
p_list = []
for i in range(1,4):
p = Process(target=foo,args=(i,))
p.start()
p_list.append(p)
print(p_list)
for p in p_list:
p.join()
end = time.time()
print(end-start) #3s多 or 6s多 ? 正解:3s多
print('主')

这样子代码的效果 是一样的,但是看上去就更加的简单美观了

Process其他用法

pid(),getpid()和getppid()

其他比较常见的用法是pid(),getpid()和getppid(),他们可以分别用在子进程和父进程中。我们可以直接用代码来表示用法

from multiprocessing import Process,current_process
import time,os def task(): print('子进程 start')
print('在子进程中查看自己的pid',current_process().pid) # 在子进程中查看自己的pid
print('在子进程中查看父进程的pid',os.getppid()) #
time.sleep(200)
print('子进程 end') if __name__ == '__main__': p = Process(target=task)
p.start()
print('在主进程查看子进程的pid',p.pid) # 一定要写在 start()之后
print('主进程的pid',os.getpid())
print('主进程的父进程pid',os.getppid())
print('主')

这些用法都是站在当前进程的角度

os.getpid():获取当前进程的pid

os.getppid():获取当前进程的父进程的pid

子进程对象.pid:获取当前进程的子进程pid

name和is_alive

p.name:进程的名称

p.is_alive():如果p仍然运行,返回True,没有运行则返回False

from multiprocessing import Process,current_process
import time
def foo():
print('进程 start')
# print('--------------------- ',current_process().name)
time.sleep(2)
print('进程 end') if __name__ == '__main__':
p = Process(target=foo)
# p2 = Process(target=foo,name='rocky') p.start()
# p2.start()
print(p.is_alive()) # True
time.sleep(5)
print(p.is_alive()) # 代码运行完了就算死了 False
print(p.name)
# print(p2.name)
print('主')

terminate()

p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁

from multiprocessing import Process,current_process
import time
def foo():
print('进程 start')
# print('--------------------- ',current_process().name)
time.sleep(4294967)
print('进程 end') if __name__ == '__main__':
p = Process(target=foo) p.start()
p.terminate() # 给操作系统发了一个请求
print(p.is_alive()) # True
p.join()
print(p.is_alive()) # False print('主')

如上述代码,在使用terminate之后程序并不会睡4294967(sleep所能睡的最大的值,不要问我是怎么知道的),而是会直接结束,当然foo()函数里的所有代码都不会运行,当然,如果你在terminate之前sleep一下的话,那么在执行terminate之前的foo()里的代码还是会运行的

守护进程

守护--》伴随

本质也是一个子进程

主进程的代码执行完毕守护进程直接结束。但是此时主进程可能没有结束.

from multiprocessing import Process
import time
def foo():
print('守护进程 start')
time.sleep(5)
print('守护进程 end') if __name__ == '__main__':
p = Process(target=foo)
p.daemon = True # 把这个子进程定义为了守护进程
p.start()
time.sleep(2)
print('主')

守护进程在主进程结束后也会直接结束,上述代码中 守护进程 end 并不会被执行

from multiprocessing import Process
import time
def foo():
print('守护进程 start')
time.sleep(3)
print('守护进程 end') def task():
print('子进程 start')
time.sleep(5)
print('子进程 end') if __name__ == '__main__':
p = Process(target=foo)
p2 = Process(target=task)
p.daemon = True # 把这个子进程定义为了守护进程
p.start()
p2.start()
time.sleep(1)
print('主')

而子进程则不一样,他并不会随着主进程结束而结束,所以它会变成孤儿进程

Process用法与进程详解的更多相关文章

  1. PHP 进程详解

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  2. windows进程详解

    1:系统必要进程system process    进程文件: [system process] or [system process]进程名称: Windows内存处理系统进程描述: Windows ...

  3. Linux学习之守护进程详解

    Linux系统守护进程详解                                                              ---转自:http://yuanbin.blog ...

  4. supervisord管理进程详解

    supervisord管理进程详解 supervisor配置详解(转) 官网 Linux后台进程管理利器:supervisor supervisor使用详解

  5. Hadoop的由来、Block切分、进程详解

    Hadoop的由来.Block切分.进程详解 一.hadoop的由来 Google发布了三篇论文: GFS(Google File System) MapReduce(数据计算方法) BigTable ...

  6. 使用supervisor管理tomcat,nginx等进程详解

    1,介绍 官网:http://supervisord.org Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时 ...

  7. linux 中的进程wait()和waitpid函数,僵尸进程详解,以及利用这两个函数解决进程同步问题

    转载自:http://blog.sina.com.cn/s/blog_7776b9d3010144f9.html 在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / wait ...

  8. python中进程详解

    1:pdb调试:基于命令行的调试工具,非常类似gnu和gdb调试,以下是常用的调试命令: 可以python -m pdb xxx.py(你的py文件名)进入命令行调试模式 命令 简写命令 作用 bea ...

  9. setsockopt()用法及参数详解

    setsockopt()用法(参数详细说明) int setsockopt(SOCKET s,int level,int optname,const char* optval,int optlen); ...

随机推荐

  1. Weblogic wls9_async_response 反序列化远程命令执行漏洞(CVE-2019-2725)复现

    一.     漏洞简介 漏洞编号和级别 CVE编号:CVE-2019-2725,危险级别:高危,CVSS分值:9.8. CNVD 编号:CNVD-C-2019-48814,CNVD对该漏洞的综合评级为 ...

  2. RESTful基本概念

    文章目录 01 前言 02 RESTful的来源 03 RESTful6大原则 1. C-S架构 2. 无状态 3.统一的接口 4.一致的数据格式 4.系统分层 5.可缓存 6.按需编码.可定制代码( ...

  3. 洛谷P5520 【[yLOI2019] 青原樱】

    这题是小学奥数啊. 题意:求\(m\)个不同物品两两不相邻的方案数. 直接排列组合. 我们可以减掉他们之间最少需要空出来的位数--\(m-1\)个空位 像这样,我们只用留\(m-1\)个空位放在每两个 ...

  4. Kong05-Kong 的健康检查和监控

    您可以让 Kong 代理的 API 使用 ring-balancer , 通过添加包含一个或多个目标实体的upstream 实体来配置,每个目标指向不同的IP地址(或主机名)和端口.ring-bala ...

  5. [BZOJ4553][HEOI2016/TJOI2016]序列

    传送门 好像是DP再套个裸的CDQ? 树套树是不可能写树套树的,这辈子都不可能写树套树的 对于一个 \(i\) ,设它最小为 \(a_i\) ,原数为 \(b_i\) ,最大为 \(c_i\) \(f ...

  6. python——掌握sorted函数的用法

    看本篇文章的前提是掌握 00函数的基本概念.01函数参数传递方式 可参考本人博客文章 sorted函数 是一个内建函数,接收一个可迭代对象,按照指定类型.指定顺序进行排序,特点是返回一个新的列表,不改 ...

  7. VMware下Centos7-Minimal上网配置

    1.Centos7下载 http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1810.iso 2.推荐 ...

  8. spring+struts2引起的错误被记忆问题

    标题表述的比较模糊,详细情况是这样的: 目前开发的一个管理系统,当使用出现异常时会自动跳转到错误页.其处理流程是“发生异常——跳转到错误处理action——错误页”. 但是出现了一个bug,即某个操作 ...

  9. Conda/Miniconda/Anaconda 常用命令整理及介绍

    作者:HELO 出处:http://www.cnblogs.com/HELO-K 欢迎转载, 转载时请保留此声明, 谢谢! 在这里整理一份全一点的 Conda 常用命令, 方便大家日常使用时参考, 一 ...

  10. 【持续更新】【pat】pat刷题技巧记录

    修改code completion快捷键位CTRL+ENTER,帮助提示函数名称 修改命令行提示符的属性,开启快速编辑模式,方便调试 添加c++11语言标准支持 开启代码调试功能 对输入的字符串进行切 ...