美文网首页
进程与多进程

进程与多进程

作者: 遇明不散 | 来源:发表于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