美文网首页
进程与多进程

进程与多进程

作者: 遇明不散 | 来源:发表于2019-02-05 21:03 被阅读1次

    多任务编程

    可以有效的利用计算机资源,同时执行多个任务

    进程

    定义

    进程就是程序在计算机中一次执行的过程

    程序与进程的区别

    程序是一个静态文件的描述,不占计算机的系统资源
    进程是一个动态的过程,占有CPU内存等资源,有一定的生命周期
    同一个程序的不同执行过程即为不同的进程

    什么决定了进程的创建

    • 用户通过应用层程序进行进程的创建申请
    • 调用操作系统接口进行进程创建
    • 告知系统内核创建新的进程提供给应用层使用

    进程如何占有CPU

    • 同一个内核同一个时刻只能运行一个进程
    • 多个进程对内核资源进行抢占,由操作系统进行分配
    • 哪个进程占有计算机内核我们称为该进程占有CPU的时间片

    进程在运行过程中的形态和附带内容

    PCB(进程控制块)

    在Linux和Unix操作系统中,进程创建后会在内存中开辟一块空间存放进程的相关信息,这个空间称为PCB。

    • PID:
      在操作系统中进程的唯一标,是一个大于0的正整数,由操作系统分配。
      ps aux 查看进程列表信息
    • 虚拟内存:
      每个进程占有4G内存地址空间,这里的内存指的是虚拟内存。
    • 进程状态:
      • 三态
        • 就绪态:进程具备运行条件,等待系统分配处理器以便运行
        • 运行态:进程占有CPU处于运行状态
        • 等待态:又称为阻塞或者睡眠态,指进程不具备运行条件,正在等待某些条件的达成
      • 五态
        • 新建态:创建一个进程的过程,直接表现为执行某个程序或者在程序中创建新的进程
        • 终止态:进程执行结束,完成回收的过程
      • Linux下进程状态表示
        • D:等待态(不可中断)
        • S:等待态 (可中断)
        • T:等待态(暂停)
        • R:运行态
        • Z:僵尸态
        • +:前台进程
        • N:低优先级的进程
        • <:高优先级的进程
        • l:有进程链接
        • s:会话组

    进程的优先级

    优先级往往决定了一个进程的执行权限和占有系统资源的优先级

    • 优先级范围
      -20 ~ 19 数越小,优先级越高,用户创建进程默认优先级为0
    • top 命令
      动态查看系统进程运行情况
    • nice 命令
      以指定的优先级运行某个进程
      nice -9 ./while.py 以9的优先级运行程序
      sudo nice --9 ./while.py 以-9的优先级运行程序
      renice n PID 修改一个正在运行的进程的优先级

    父子进程

    在系统中除了初始化进行之外每个进程都是由父进程创建的,每个进程有一个唯一的父进程,可能有多个子进程
    os模块:

    • os 模块提供大量和系统相关的功能函数接口
    • os 模块的使用时系统相关的,在不同的系统中,可能使用方法不同

    os.fork()

    • 平台:只能在linux和unix下使用

    • 功能:创建一个新的进程

    • 参数:无

    • 返回值:

      • < 0 表示进程创建失败
      • == 0 在子进程中fork的返回值为0
      • > 0 在父进程中fork的返回值大于0
    • 注意:

      • 父进程中fork之前的内容,子进程会同样复制,但是父子进程空间内容的修改不会相互影响
      • 父子进程在执行上互不影响,理论上不一定谁先执行
      • 子进程虽然复制父进程的空间,但也有自己独特的德行,比如自己的PID,进程控制块,进程栈等。父进程中fork的返回值即为创建的子进程的PID号。
      • 子进程的退出不会影响父进程

    进程相关函数

    • os.getpid() 获取当前进程的PID号
    • os.getppid() 获取当前进程父进程的PID号
    • os._exit(status)
      功能:结束一个进程
      参数:一个数字表示进程的退出状态,通常0表示正常退出进程,其他数字表示非正常退出
    • sys.exit([status])
      功能:结束一个进程,如果处理了抛出的异常则不结束进程
      参数:一个数字表示进程的退出状态,还可以是一个字符串,则在进程退出时会打印这个字符串

    僵尸进程

    定义:子进程先于父进程退出,父进程没有对子进程的退出做出相应的处理,此时子进程就会变成僵尸进程
    影响:进程退出后,仍有部分信息残留在内存中占用空间,大量的僵尸进程会影响系统运行,所以应该尽量避免僵尸进程的产生。

    处理僵尸进程的方法

    • 让父进程先退出 (不好控制)
    • 父进程处理子进程的退出 (阻塞父进程的运行)
      • os.wait()
        阻塞函数:进程处于等待状态,等待某种条件的达成才会继续运行
        功能:等待子进程退出进行处理
        参数:
        返回值:返回一个包含两个元素的元组,第一个是退出的子进程的PID号,第二个是子进程的退出状态
      • os.waitpid(pid,option)
        功能:同wait,处理子进程退出使其不会变成僵尸
        参数:
        • pid -1 表示等待任意子进程退出
        • pid >0 表示等待指定进程号的子进程退出
        • option 0 表示阻塞等待
        • option WNOHANG 表示非阻塞状态
        • wait() === waitpid(-1,0)
    • 创建二级子进程处理
      原理:让子进程创建二级子进程,创建完成就退出,二级子进程成为孤儿进程
    • 在父进程中使用信号处理的方法忽略子进程发来的信号signal(SIGCHLD,SIG_ING)

    孤儿进程

    定义:父进程先于子进程退出,此时子进程就会变为孤儿进程
    影响:当一个进程变为孤儿进程,系统会自动的使用一个进程成为孤儿进程的父进程。当孤儿进程退出时,该系统会自动回收孤儿,使它不会成为僵尸。所以孤儿进程对系统资源没什么影响。

    守护进程

    • 生命周期长
    • 与前端控制台无关
    • 后台运行,一般用作系统进程或者自动化运行进程

    多进程

    更方便高效的进程创建方法

    • multiprocessing模块 (标准库模块)

    创建进程的步骤

    • 将要完成的事件封装成一个函数
    • 使用multiprocessing提供的接口函数创建j进程
    • 使新的进程和指定的函数相关联去完成函数中的工作,并启动进程
    • 对进程进行回收处理

    进程的回收

    • 作用:阻塞等待对应子进程的退出,然后回收子进程
    • 注意:内核会帮助应用层记录子进程的退出情况,当使用join函数时内核会及时返回进程状态给应用层进行处理

    创建子进程:

    Process()

    • 参数:
      • target 指定要绑定的函数
      • name 给创建的进程起一个名字
      • args 需要一个元组,给target指定的函数按位置传参
      • kwargs 需要一个字典,给taregt指定的函数按键值传参
    • 属性与方法(p代表一个进程)
      • p.name 进程名称
      • p.pid 进程PID
      • p.daemon
        • False(默认值)表示主进程运行结束后,不会影响子进程的运行,直到所有子进程运行完毕,进程才会结束
        • True 主进程运行完毕则所有子进程也不再运行一起退出。
        • 注意:
          • 该属性的设置必须要在start()
          • 该属性的设置并不是将进程设置为linux/unix中的守护进程
      • p.is_alive() 进程状态
      • p.start() 启动子进程
      • p.join() 回收子进程
        • 参数:p.join(timeout) 设置最长阻塞时间,如果超过这个时间还没有子进程退出,则不会继续等待
    • 注意
      • 函数当付给Processtarget变量后函数内容就是对应进程的进程内容,此时函数才有特殊性
      • 多个子进程和父进程之间的执行互不影响

    多进程的优缺点

    优点

    • 可以并行执行多个任务,提高运行效率
    • 空间独立,数据安全
    • 创建方便

    缺点

    • 进程的创建和销毁过程需要消耗较多的计算机资源
    • 在需要频繁的创建和销毁较多进程情况下,资源消耗过多,不适宜使用多进程完成任务

    进程池

    什么是进程池

    在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
    进程池可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

    进程池的创建

    • 创建进程池,在池内放入合适数量的进程
    • 将事件加入进程池的等待队列
    • 使用进程池内的进程不断的执行等待事件
    • 所有事件处理完毕后,关闭回收进程池

    进程池的具体操作

    • Pool
      • 功能:创建进程池
      • 参数:processes 进程池中进程的数量
    • apply_async()
      • 功能:以异步的方式将要执行的事件放入进程池
      • 参数:
        • func 要执行的函数
        • args 给函数按位置传参
        • kwds 给函数按照键值传参
      • 返回值:
        返回事件执行后的返回值对象,可以通过调用get()函数获取事件函数return的内容
    • apply()
      功能:按照顺序添加要执行的事件,执行一个再添加一个
    • close()
      功能:关闭进程池,使其不能再加入新的事件
    • join()
      功能:阻塞等待进程池将事件都执行结束后回收进程池
    • map()
      功能:类似于内建函数map,将第二个参数的迭代对象中的数据逐个带入第一个函数作为参数。只不过兼顾了apply_async功能,将函数放入进程池

    创建自己的进程类

    • 继承Process类以获取原有的属性
    • 实现自己的功能部分
    • 使用自己的类创建进程即可

    相关文章

      网友评论

          本文标题:进程与多进程

          本文链接:https://www.haomeiwen.com/subject/bmhfsqtx.html