进程
1.操作系统发展史
2)联机批处理系统
支持多用户去使用一个计算机机房。
缺点:
在作业输入和结果输出时,主机的高速CPU仍处于空闲状态
3) 脱机批处理系统
高速磁盘:
提高文件的读取速度。
优点:
提高CPU的利用率
卫星机:一台不与主机直接相连而专门用于与输入/输出设备打交道的。
其功能是:
- 从输入机上读取用户作业并放到输入磁带上。
- 从输出磁带上读取执行结果并传给输出机。
4)多道技术(基于单核情况下研究):
- 单道:
多个使用使用CPU时是串行。
- 多道技术:计算机内存中同时存放几道相互独立的程序
- 空间上的复用(*******):
一个CPU可以提供给多个用户去使用。
- 时间上的复用(*******):
切换 + 保存状态
IO操作:
input()
print()
time.sleep(3)
1) 若CPU遇到IO操作,会立即将当前执行程序CPU使用权断开。
优点:
CPU的利用率高。
2) 若一个程序使用CPU的时间过长,会立即将当前执行程序CPU使用权断开。
缺点:
程序的执行率降低。
- 并发与并行:
并发: 指的是看起来像同时在运行,多个程序不停 切换 + 保存状态。
并行: 真实意义上的同时运行,在多核(多个CPU)的情况下,同时执行多个程序。
2.进程
- 程序与进程
- 程序: 一堆代码。
- 进程: 一堆代码运行的过程。
- 进程调度:
当代操作系统调度:
时间片轮转法 + 分级反馈队列
1)先来先服务调度:
a,b程序,若a程序先来,先占用CPU。
缺点:
程序a先使用,程序b必须等待程序a使用cpu结束后才能使用。
2)短作业优先调度:
a,b程序,谁的用时短,先优先调度使用cpu。
缺点:
若程序a使用时间最长,有N个程序使用时间短,
必须等待所有用时短的程序结束后才能使用。
3) 时间片轮转法
CPU执行的时间1秒中,加载N个程序,要将1秒等分成多N个时间片。
4) 分级反馈队列
将执行优先分为多层级别。
- 1级; 优先级最高。
- 2级: 优先级第二,以次类推。
- 3级
....
创建进程方式一:
# 1.定义一个任务
import timefrom multiprocessing import Process def task(name): print(f'{name}的任务开始执行') time.sleep(1) print(f'{name}的任务已经结束') # 在linux/mac系统下不会报错 # p = Process(target=task, args=('jason',)) if __name__ == '__main__': # target=执行函数的地址 p = Process(target=task, args=('jason',)) # 向操作系统提交创建进程的任务 p.start() print('主进程')
运行结果:
主进程
jason的任务开始执行
jason的任务已经结束
创建进程的方式二:
#创建进程方式二: #1.自定义一个类,并继承Process
import timefrom multiprocessing import Process class MyProcess(Process): # 父类的方法 def run(self): print('任务开始执行') time.sleep(1) print('任务已经结束') if __name__ == '__main__': p = MyProcess() p.start() # p.start() print('主进程')
运行结果:
主进程 任务开始执行 任务已经结束
join方法:
用来告诉操作系统,让子进程结束后,父进程再结束
from multiprocessing import Process import time def task(name): print(f'{name} start...')0 time.sleep(2) print(f'{name} over..') if __name__ == '__main__': p = Process(target=task, args=('jason', )) p.start() # 告诉操作系统,开启子进程 p.join() # 告诉操作系统,等子进程结束后,父进程再结束。 print('主进程')
打印结果:
jason start... jason over.. 主进程
from multiprocessing import Process import time def task(name, n): print(f'{name} start...') time.sleep(n) print(f'{name} over..') if __name__ == '__main__': p1 = Process(target=task, args=('jason', 1)) p2 = Process(target=task, args=('egon', 2)) p3 = Process(target=task, args=('sean', 3)) p1.start() p2.start() # 告诉操作系统,开启子进程 p3.start() # 告诉操作系统,开启子进程 p1.join() # 告诉操作系统,等子进程结束后,父进程再结束。 p2.join() p3.join() print('主进程')
打印结果:
sean start... jason start... egon start... jason over.. egon over.. sean over.. 主进程
进程间数据是相互隔离的
主进程与子进程会产生各自的名称空间
from multiprocessing import Process x = 100 def func(): print('执行func函数...') global x x = 200 print(1111) if __name__ == '__main__': p = Process(target=func) p.start() p.join() print(x) print('主')
运行结果:
执行func函数... 1111 100 主
进程对象的属性
current_process().pid: 获取子进程号
os.getpid(): 获取主进程pid号
cmd中查看进程号: tasklist |findstr 进程号
进程号回收的两种条件:
1.join,可以回收子进程与主进程。
2.主进程正常结束,子进程与主进程也会被回收。
os.getppid() 主主进程号
终止子进程;判断子进程是否存活
from multiprocessing import Process from multiprocessing import current_process import os # 与操作系统交互 import time def task(name): print(f'{name} start...', current_process().pid) time.sleep(1) print(f'{name} over..', os.getpid()) if __name__ == '__main__': p = Process(target=task, args=('jason', )) p.start() # 告诉操作系统,开启子进程 print(p.pid) # 判断子进程是否存活 print(p.is_alive()) # 直接告诉操作系统,终止 子进程 p.terminate() time.sleep(0.1) # 判断子进程是否存活 print(p.is_alive()) p.join() # 告诉操作系统,等子进程结束后,父进程再结束。 print('主进程', os.getpid()) print('主主进程', os.getppid()) time.sleep(100)
打印结果:
True False 主进程 9688 主主进程 10680
守护进程
主进程结束,子进程也一起结束
from multiprocessing import Process from multiprocessing import current_process import time def task(name): print(f'{name} start...', current_process().pid) time.sleep(5) print(f'{name} over..', current_process().pid) print(f'管家{name}') if __name__ == '__main__': p1 = Process(target=task, args=('jason', )) # 添加守护进程参数 p1.daemon = True # True代表该进程是守护进程 要在start()之前设置 p1.start() print(f'egon ...')
打印结果:
egon ...
- 进程的三个状态:
- 就绪态:
所有进程创建时都会进入就绪态,准备调度。
- 运行态:
调度后的进程,进入运行态。
- 阻塞态:
凡是遇到IO操作的进程,都会进入阻塞态。
若IO结束,必须重新进入就绪态。
- 同步和异步:
指的是提交任务的方式。
- 同步:
若有两个任务需要提交,在提交第一个任务时,
必须等待该任务执行结束后,才能继续提交并执行第二个任务。
- 异步:
若有两个任务需要提交,在提交第一个任务时,
不需要原地等待,立即可以提交并执行第二个任务。
- 阻塞与非阻塞:
- 阻塞:
阻塞态。遇到IO一定会阻塞。
- 非阻塞:
就绪态
运行态
面试题: 同步和异步,阻塞和非阻塞是同一个概念吗?
强调: 不是同一个概念,不能混为一谈!
最大化提高CPU的使用率:
尽可能减少不必要的IO操作。
进程号回收的两种条件:
1.join,可以回收子进程与主进程。
2.主进程正常结束,子进程与主进程也会被回收。
3.僵尸进程与孤儿进程(了解):
僵尸进程:
指的是子进程已经结束,但PID号还存在,未销毁.
缺点:
占用PID号,占用操作系统资源.
孤儿进程:
指的是子进程还在执行,但父进程意外结束.
操作系统优化机制:
提供一个福利院,帮你回收没有父亲的子进程.
4.守护进程:
指的是主进程结束后,该主进程产生的所有子进程跟着结束,并回收.