Process用法与进程详解

僵尸与孤儿进程

僵尸进程:父进程的子进程结束的时候父进程没有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('主')

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

原文地址:https://www.cnblogs.com/jie9527-/p/11537467.html

时间: 2024-11-17 21:32:18

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

windows进程详解

1:系统必要进程system process    进程文件: [system process] or [system process]进程名称: Windows内存处理系统进程描述: Windows页面内存管理进程,拥有0级优先.alg.exe       进程文件:alg or alg.exe 进程名称:应用层网关服务  描述:这是一个应用层网关服务用于网络共享csrss.exe      进程文件:csrss or csrss.exe 进程名称:Client/Server Runtime

Linux学习之守护进程详解

Linux系统守护进程详解                                                              ---转自:http://yuanbin.blog.51cto.com/363003/107306/,多谢分享 不要关闭下面这几个服务: acpid, haldaemon, messagebus, klogd, network, syslogd 1. NetworkManager, NetworkManagerDispatcher NetworkM

Linux挂载命令mount用法及参数详解

Linux挂载命令mount用法及参数详解 导读 mount是Linux下的一个命令,它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了. 挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的. 命令格式:mount [-t vfstype] [-o options] device dir 1.-t vfstype 指定文件系统的类型,通常不必指定,m

Linux进程详解

本文实际上是 "UNIX环境高级编程" 的读书笔记. 所以许多细节并没有表述出来, 想要刨根问底的同学建议再看看原书. 之所以把读书笔记贴到博客上, 出于两个目的: 1. 加深自己的学习效果. 2. 提供一个快速浏览的方式. 本文提到的技术在下面的环境中实际验证过: Linux version 2.6.18-164.el5 x86_64 GNU/Linux (gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)) 程序和进程 程序是指磁盘上的可执行

Android进程详解

当一个应用启动的时候,如果这个应用没有其它组件已经在运行了,那么系统就会为这个应用启动一个新的Linux进程,这个进程只有一个线程,即我们熟知的main线程.默认情况下,一个应用的所有组件都运行在一个进程和线程(main)中.这点从Logcat的打印信息可以看出,Logcat视图中的Application那一栏,打印的是当前应用的进程的name值,而通常情况下是打印出的是manifes的package的值,这是因为我们的Application的标签没有设置progress的值,如果没有设置的话,

supervisord管理进程详解

Supervisor是由python语言编写,基于linux操作系统的一款服务器管理工具, 用以监控服务器的运行,发现问题能立即自动预警及自动重启等功能. Supervisor类似于monit, monit和supervisor的一个比较大的差异是supervisor管理的进程必须由supervisor来启动, monit可以管理已经在运行的程序: supervisor还要求管理的程序是非daemon程序,supervisord会帮你把它转成daemon程序, 因此如果用supervisor来管

守护进程详解及创建,daemon()使用

一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而 且提供某种服务,不是对整个系统就是对某个用户程序提供服务.Linux系统的大多数服务器就是通过守护进程实现的.常见的守护进程包括系统日志进程 syslogd. web服务器httpd.邮件服务器sendmail和数据库服务器mysqld等. 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行.守护进

《Linux菜鸟入门》进程详解

●进程 1.进程定义 进程就是cpu未完成的工作 2.ps命令 ps  a    关于当前环境的所有进程,不是自己的也会显示 x    与当前环境无关的所有进程 f    显示进程从属关系 e    显示当前用户环境中的所有进程 l    长列表显示进程的详细信息 u    显示进程的用户信息 ps ax -o %cpu,%mem,user,group,comm,nice  指定显示进程的某些信息 %cpu   负载 mem   内存负载 user   用户 group    组 comm   

unix/linux进程详解

启动新进程 stdlib.h int system(const char *string) which equals to “sh -c string” 替换进程映像 unistd.h char **environ; int execl(const char *path, const char *arg0, ...(char *)0); int execlp(const char *file, const char *arg0, ...(char *)0); int execle(const c