进程
- 进程的概念
- 进程的概念:进程是一个具有独立功能的程序的一次运行活动,是操作系统的资源分配的基本单位
- 一个shell(linux命令)是一个系统目录下的程序,当使用某个命令时,系统为我们创建了一个进程运行这个程序
- 僵尸进程:子进程已经运行完成结束, 但是父进程还没有来得及对子进程的相关资源进行回收
- 不回收的话对系统资源的影响比较大
- 孤儿进程:父进程退出, 子进程还没有退出 子进程就变成孤儿进程
- init进程接管孤儿进程 init进程负责回收孤儿进程的资源
- 进程的三个典型状态
- 就绪:已经分配除CPU之外所有的资源
- 运行:正在占用CPU资源执行
- 阻塞:正在等待事件/数据的条件
- 进程与程序的区别
- 进程与程序拥有资源的区别:
- 程序:占用硬盘空间,以程序/二进制代码的形式存储在硬盘中
- 进程:占用内存/CPU等资源,程序运行一次活动会占用内存和CPU的资源
单任务/多任务
- 单任务:串行执行效率低
- 多任务:就是操作系统同时运行多个任务,可以充分利用cpu的多核,这样执行代码的效率高,也可以实现一些需要同时运行的代码逻辑
并行与并发:
- 并行:多个任务在同一时刻执行,指的是当任务数小于cpu核数的时候,任务可以利用多核完成一起执行
- 并发:多个任务在同一个时间段执行,指的是当cpu任务书多余cpu核数的时候,通过操作系统的各种任务调度算法,实现多个任务 一起执行(但是实际上不是同一时刻执行因为cpu的切换任务的速度特别快,在效果上看相当于在一起执行)
操作系统中进程的PID标示
- PID(Process identification)是一个进程在操作系统中的唯一标示,每次程序运行操作系统会随机分配一个PID号给到对应进程,不能通过直接指定的方式来确定PID标示。
- 获取PID进程标示的方法:
- ps -aux | grep process name 获取所有进程的信息
- os.getpid() 获取当前进程的PID
- 进程的实例.pid 获取创建出来的子进程的PID
multiprocessing跨平台多进程模块使用
- multiprocessing
- multiprocessing是跨平台的多进程模块,用来进行多进程软件的开发
- multiprocessing.Process类
- 作用
- 通过创建multiprocessing.Process的实例可以创建对应的子进程,通过对实例的控制可以实现对子进程的操作
- 创建Process子进程实例
- process_object = multiprocessing.Process(target=None, args=(), name="")
- 创建Process类的实例时__init__方法常用参数
- target 表示子线程入口函数代码None表示nothing
- args 表示入口代码运行所需要的参数元组 args把数据传递给普通形参
- kwargs 表示入口代码运行所需要的参数字典 kwargs 把数据传递给缺省参数
- name 指定进程的名称,也可以不指定,系统会自动分配
- Process 实例常用方法和属性
- start() 启动进程
- is_alive() 判断进程是否还存活
- join(time) 阻塞程序(子进程结束后才能继续主进程),加time可以设置等待时间,不写time的值默认等待到条件满足
- 在设计多进程的时候最好都要用join来回收内存资源,不然会造成僵尸程序
- terminate() 终止子进程 - 会让子进程变成僵尸程序,需要注意要用join()来回收进程资源
- name 进程的名称
- pid 进程的PID号
- (注意:在进程中默认已经有一个进程了(主进程))
- 父子进程关于数据的共享
- 父子进程在独立的内存地址空间,并不能直接进行全局数据的共享
- 在创建子进程的时候会将父进程中的数据复制一份到子进程中,后面的运行数据是独立状态的
- multiprocessing-Queue方法(进程间的通信)
- 作用:通过创建Queue列队,可以在进程间通过传递Queue列队来传递进程间的参数
- 列队的特点:先进先出,后进后出
- 创建queue列队
- 变量名 = multiprocessing.Queue(maxsize) maxsize参数表示列队的容量,当maxsize为0的时候标示列队的容量为无穷大(慎用)
- Queue实例对象常用方法(假设已经创建实例名为q)
- 添加数据到列队
- q.put(obj, block=True, timeout=None)
- block 默认为True表示阻塞状态列队满了会阻塞,False为非阻塞状态,列队满后会报错; timeout参数只对阻塞模式有效,等待响应时间如无响应会继续向下执行代码;
- 从列队中取出数据
- q.get(block=True, timeout=None) 参数同put方法
- 获取列队中的消息数量
- q.size( )
- 判断列队是否为空/满
- q.empty( )/ q.full( ) 返回True/False
- 文件信息传递实例
- multiprocessing.Pool (类)进程池
- 进程池:
- 提前缓存一定的资源,以备不时之需重复的使用
- 优点:
- 节约等待和销毁资源的时间
- 建立进程池与常用方法
- 创建进程池
- pool_object = multiprocessing.Pool(processes=None) process表示进程池的容量 进程满后将会阻塞,直到有进程结束并成功向资源池中添加进程后
- 向进程池中添加任务
- pool_object.apply(func, args=()) 以阻塞的方式向进程池中添加任务
- 特点:添加到进程池中的任务会加到任务列队中等待上一个任务结束后会执行新的任务,实际上apply()方法是依赖apply_async的底层实现的,在其方法上增加了get()的函数,使添加任务的时候会默认阻塞等待上一个进程结束
- pool_object.apply_async(func, args=()) 以非阻塞的方式向进程池中添加任务
- 特点:将任务添加到任务列队中,进程池中的任务会并发执行,不会等上一个任务结束再进行下一个任务
- 关闭进程池
- pool_object.close() 关闭进程池后 进程池将不能够再接受新的任务
- 终止进程池
- pool_object.terminate()
- 阻塞进程池
- pool_object.join()
- 注意:要先关闭或者终止进程池,然后再join()
- 进程池间进程的通信方法---multiprocessing.Manager( ).Queue( )
- 使用Queue时的限制:
- 具有共同祖先
- 由于进程池中的任务是调用进程池的方法来创建的进程,他们的父进程并不统一,不能使用Queue来进行通信
备注:文件相关操作
- os.path.getsize(文件名 ) 获取文件的大小
- os.path.getmtime/ctime(文件名 ) 获取文件的修改时间
拓展-MP中的几个函数
- 返回当前系统的可用的逻辑处理核心数
- multiprocessing.cpu_count()
- 返回当前的Process实例
- multiprocessing.current_process()
- 返回当前进程的子进程列表
- multiprocessing.active_children()
注意点:
- 不能再子进程中使用input(),会报错,若要使用需要关闭父进程的文件标识符