zoukankan      html  css  js  c++  java
  • 34 进程 pid ppid 并发与并行,阻塞与非阻塞 join函数 process对象 孤儿进程与僵尸进程

    进程与程序

    一个正在被运行的程序就称之为进程,是程序具体执行过程,一种抽象概念

    进程来自于操作系统
    多进程:多个正在运行的程序.

    测试:

    import time
    while True
    time.sleep(1)

    多次运行该文件,就会产生多个python.exe进程,可以通过tasklist来查看运行的程序

    PID和PPID

    pid:系统会给每一个进程分配一个进程编号

    验证:

    tasklist 用于查看所有的进程信息

    taskkill /f /pid pid 该命令可以用于结束指定进程

    # 在python中可以使用os模块来获取pid
    import os
    print(os.getpid())

    PPID

    当一个进程a开启了另一个进程b时,a称为b的父进程,b称为a的子进程

    在python中可以通过os模块来获取父进程的pid

    # 在python中可以使用os模块来获取ppid
    import os
    print("self",os.getpid()) # 当前进程自己的pid
    print("parent",os.getppid()) # 当前进程的父进程的pid

    如果是在pycharm中运行的py文件,那pycahrm就是这个python.exe的父进程,当然你可以从cmd中来运行py文件,那此时cmd就是python.exe的父进程

    进程和程序的区别

    程序就是一堆计算机可以识别文件,程序在没有被运行就是躺在硬盘上的一堆二进制

    运行程序时,要从硬盘读取数据到内存中,CPU从内存读取指令并执行 ,

    一旦运行就产生了进程

    一个程序可以多次执行 产生多个进程,但是进程之间相互独立

    当我们右键运行了一个py文件时 ,其实启动的是python解释器,你的py文件其实是当作参数传给了解释器

     

    阻塞 非阻塞 并行 并发

    阻塞 : 程序遇到io操作时就进入了阻塞状态

    本地IO input print sleep read write

    网络IO recv send

    非阻塞: 程序正常运行中 没有任何IO操作 就处于非阻塞状态

    阻塞 非阻塞 说的是程序的运行状态

    并发: 多个任务看起来同时在处理 ,本质上是切换执行 速度非常快

    并行: 多个任务真正的同时执行 必须具备多核CPU 才可能并行

    并发 并行 说的是 任务的处理方式

     

     

    进程有三种状态

    就绪态,运行态,和阻塞态

    多道技术会在进程执行时间过长或遇到IO时自动切换其他进程,意味着IO操作与进程被剥夺CPU执行权都会造成进程无法继续执行

    进程的创建

    但凡是硬件,都需要有操作系统去管理,只要有操作系统,就有进程的概念,就需要有创建进程的方式

    而对于通用系统(跑很多应用程序),需要有系统运行过程中创建或撤销进程的能力,主要分为4种形式创建新的进程

    关于创建的子进程,UNIX和windows

      1.相同的是:进程创建后,父进程和子进程有各自不同的地址空间(多道技术要求物理层面实现进程之间内存的隔离),任何一个进程的在其地址空间中的修改都不会影响到另外一个进程。

      2.不同的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。但是对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的。

    进程的销毁

    1. 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)

    2. 出错退出(自愿,python a.py中a.py不存在)

    3. 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,可以捕捉异常,try...except...)

    4. 被其他进程杀死(非自愿,如kill -9)

    process类常用属性
    Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)
    
    强调:
    1. 需要使用关键字的方式来指定参数
    2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

        参数介绍:

    group参数未使用,值始终为None

    target表示调用对象,即子进程要执行的任务

    args表示调用对象的位置参数元组,args=(1,2,'egon',)

    kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}

    name为子进程的名称

    方法介绍:

     
    1 p.start():启动进程,并调用该子进程中的p.run() 
     2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法  
     3 
     4 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
     5 p.is_alive():如果p仍然运行,返回True
     6. p.exitcode:获取退出码

    7 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
     8 p.name:进程的名称

    join函数

    父进程等待子进程结束后继续执行

    案例1:

    """
    当你开启了一个子进程 并且给他一个任务 如果你希望知道这个任务什么时候完成 那就需要等待

    """
    import  time
    from multiprocessing import Process

    def task(i):
    # print('出去了')
    time.sleep(2)
    print('%s回来了'%i)

    if __name__ == '__main__':
    start_time=time.time()
    p1=Process(target=task,args=(1,))
    p2 = Process(target=task, args=(2,))
    p3 = Process(target=task, args=(3,))


    p1.start()
    p2.start()
    p3.start()



    p1.join()
    p2.join()
    p3.join()

    # p3.join()
    # p2.join()
    # p1.join()


    end_time=time.time()
    print(end_time - start_time)
    print('over')

    python中开启子进程的两种方式

    方式1:

    实例化Process类

    from multiprocessing import Process
    import time

    def task(name):
       print('%s is running' %name)
       time.sleep(3)
       print('%s is done' %name)
    if __name__ == '__main__':
       # 在windows系统之上,开启子进程的操作一定要放到这下面
       # Process(target=task,kwargs={'name':'egon'})
       p=Process(target=task,args=('jack',))
       p.start() # 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态
       print('======主')

    方式2:

    继承Process类 并覆盖run方法

    from multiprocessing import Process
    import time

    class MyProcess(Process):
       def __init__(self,name):
           super(MyProcess,self).__init__()
           self.name=name

       def run(self):
           print('%s is running' %self.name)
           time.sleep(3)
           print('%s is done' %self.name)
    if __name__ == '__main__':
       p=MyProcess('jack')
       p.start()
       print('主')

    需要注意的是

    1.在windows下 开启子进程必须放到__main__下面,因为windows在开启子进程时会重新加载所有的代码造成递归创建进程

    2.第二种方式中,必须将要执行的代码放到run方法中,子进程只会执行run方法其他的一概不管

    进程间内存相互隔离

    from multiprocessing import Process
    import time

    name = '千万'


    def task():
    name = '哇塞'
    print('改过了')
    print('子进程的%s' % name)


    if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    time.sleep(3)
    print(name)

    孤儿进程与僵尸进程

    孤儿进程

    孤儿进程指的是开启子进程后,父进程先于子进程终止了,那这个子进程就称之为孤儿进程

    孤儿进程是无害的,有其存在的必要性,在父进程结束后,其子进程会被操作系统接管。

    僵尸进程

    僵尸进程指的是,当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被操作系统接管,子进程退出后操作系统会回收其占用的相关资源!

    僵尸进程的危害:

    由于子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。
    在Linux中,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,
    在python中,已经封装好了wait操作不需要我们自己清理。
    但是系统所能使用的进程号是有限的,如果大量的产生[僵死进程],将因为没有可用的进程号而导致系统不能产生新的进程. 此为僵尸进程的危害,应当避免。












































  • 相关阅读:
    cad 创建自定义菜单
    标准C++的类型转换符
    Assert usages
    c++排序算法与模板和STL_zhuan
    C++ 中int,char,string,CString类型转换
    C++ 之 C style string
    数据库优化细节——转
    C++容器——zhuan
    公共类库_address:http://www.cnblogs.com/wuhuacong/archive/2012/03/26/2418786.html
    C++学习篇——C++ STL中迭代器介绍(收集)
  • 原文地址:https://www.cnblogs.com/komorebi/p/10957655.html
Copyright © 2011-2022 走看看