操作系统发展史
1.穿孔卡片
手工操作,且一个计算机机房,只能被一个用户使用
2.联机批处理系统
支持多用户去使用一个计算机机房,主机与输入机之间增加一个存储设备——磁带,在运行于主机上的监督程序的自动控制下,计算机可自动完成

3.脱机批处理系统
为克服与缓解:高速主机与慢速外设的矛盾,提高CPU的利用率
特征是:增加一台不与主机直接相连而专门用于与输入/输出设备打交道的卫星机。主机与卫星机可并行工作,二者分工明确,可以充分发挥主机的高速计算能力。
高速磁盘: 提高文件的读取速度
为改善CPU的利用率,又引入了多道程序系统。
4.多道程序系统
所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行,并允许它们交替在CPU中运行,当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序
单道程序运行过程
多个使用者使用CPU时是串行的

在A程序计算时,I/O空闲, A程序I/O操作时,CPU空闲(B程序也是同样);必须A工作完成后,B才能进入内存中开始工作,两者是串行的,全部完成共需时间=T1+T2。
多道程序运行过程
将A、B两道程序同时存放在内存中,它们在系统的控制下,可相互穿插、交替地在CPU上运行
* 空间上的复用: 一个CPU可以提供给多个用户使用 * 时间上的复用: 切换+保存状态 1.若CPU遇到IO操作,会立即将当前程序CPU使用权断开 优点: CPU利用率高 2.若一个程序使用CPU的时间过长,会立即将房钱执行程序CPU使用权断开 缺点: 程序执行率降低
多道程序系统的出现,标志着操作系统渐趋成熟的阶段,先后出现了作业调度管理、处理机管理、存储器管理、外部设备管理、文件系统管理等功能。
并发与并行
并发: 指的是看起来像同时在运行,多个程序不停切换+保存状态
并行: 真实意义上的同时运行,在多核的情况下,同时执行多个程序.
进程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础
1.程序与进程
程序: 一堆代码
程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念
进程: 一堆代码运行的过程
进程是程序在处理机上的一次执行过程,它是一个动态的概念。
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级:...
5.调度状态
进程执行时的间断性,决定了进程可能具有多种状态。
就绪态
所有进程创建时都会进入就绪态,准备调度
运行态
调度后的进程,进入进程态
阻塞态
凡是遇到I/O操作的进程,都会进入阻塞态,I/O结束后,必须重新进入就绪态
6.进程回收
1.进程回收的两种条件
join,可以回收子进程与主进程
主进程正常结束,子进程与主进程也会被回收
2.僵尸进程
指的是子进程已经结束,但PID号还存在,未销毁
缺点: 占用PID号,占用操作系统资源
PID号:PID是各进程的代号,运行时系统随机分配,但是进程终止后PID标识符就会被系统回收,进程号具有固定数量.
3.孤儿进程
指的是子进程还在执行,但父进程意外结束.
操作系统优化机制:自动回收此类子进程
4.守护进程
指的是主进程结束后,该主进程产生的所有子进程跟着结束,并回收.
3.进程对象的属性
1.current_process().pid
在子进程内使用,可以获取子进程号
from multiprocessing import Process from multiprocessing import current_process def task(): print('开始执行...',current_process().pid) print('结束执行') if __name__ == '__main__': p = Process(target=task) # 获得process对象 p.start() # 创建子进程 p.join() # 执行完子进程在执行主进程 print('主进程') '''开始执行... 2092 结束执行 主进程'''
2.os.getpid()
在主进程中获得主进程号.
from multiprocessing import Process from multiprocessing import current_process import os def task(): print('开始执行...',current_process().pid) print('结束执行') if __name__ == '__main__': p = Process(target=task) # 获得process对象 p.start() # 创建子进程 p.join() # 执行完子进程在执行主进程 print('主进程',os.getpid()) ''' 开始执行... 11072 结束执行 主进程 13892 '''
3.os.getppid
可以查看主主进程的进程号(pycharm中运行代码,主主进程就是pycharm)
def task(): print('开始执行...',current_process().pid) time.sleep(1) print('结束执行') if __name__ == '__main__': p = Process(target=task) # 获得process对象 p.start() # 创建子进程 p.join() # 执行完子进程在执行主进程 print('主进程',os.getpid()) print('主主进程',os.getppid()) time.sleep(1000) ''' 开始执行... 12368 结束执行 主进程 10332 # python.exe 主主进程 4152 # pycharm64.exe '''
4.join()方法
代码
会让子进程结束后再结束主进程
# 让子进程结束后,父进程才结束 from multiprocessing import Process import time def task(name): print('任务开始') time.sleep(1) print('任务结束') if __name__ == '__main__': p = Process(target= task,args=('你好',)) p.start() # 告诉操作系统,开启子进程 print('join上面的不算') p.join() # 告诉操作系统,等子进程结束后,父进程再结束 print('主进程') ''' join上面的不算 任务开始 任务结束 主进程'''
多个子程序的运行
# 多个子进程的运行 from multiprocessing import Process import time def task(name,n): print(f'{name}任务{n}开始') time.sleep(1) print(f'{name}任务{n}结束') if __name__ == '__main__': p1 = Process(target= task,args=('AAA',1)) p2 = Process(target= task,args=('BBB',2)) p1.start() # 告诉操作系统,开启子进程 p2.start() # 告诉操作系统,开启子进程 print('join上面的不算') p1.join() # 告诉操作系统,等子进程结束后,父进程再结束 p2.join() # 告诉操作系统,等子进程结束后,父进程再结束 print('主进程') ''' join上面的不算 AAA任务1开始 BBB任务2开始 AAA任务1结束 BBB任务2结束 主进程 ''' 打印时会出现任务1,2顺序的不一致,貌似是因为程序并行导致cpu分配执行打印速度导致
5.is_alive()
判断子进程是否存活
def task(): print('开始执行...',current_process().pid) if __name__ == '__main__': p = Process(target=task) # 获得process对象 p.start() # 创建子进程 print(p.is_alive()) # 判断子进程是否存活 print('主进程',os.getpid()) ''' True 主进程 3740 开始执行... 7004'''
6..terminate()
直接告诉操作系统,终止子程序
def task(): print('开始执行...',current_process().pid) if __name__ == '__main__': p = Process(target=task) # 获得process对象 p.start() # 创建子进程 # 判断子进程是否存活 print(p.is_alive()) # 告诉操作系统直接终止掉子进程 p.terminate() time.sleep(0.1) # 判断子进程是否存活 print(p.is_alive()) print('主进程',os.getpid()) ''' True False 主进程 7976'''
7.tasklist | findstr+进程号
# cmd 中查询进程号: tasklist | findstr 进程号
4.进程的创建
错误示范
from multiprocessing import Process import time # 1.定义一个任务 def task(name): print(f'{}的任务开始执行') time.sleep(1) # target = 执行函数的地址 args= 是传入函数的变量元组形式 p = Process(target=task,args=('abc0',)) # 向操作系统提交创建进程的任务 p.start() '''注意: 在Windows下:创建子进程,会将当前父进程的代码重新加载执行一次 以上执行创建子进程时会创建新的空间,会形成递归. linux/mac: 会将当前父进程代码重新拷贝一份,再去执行 '''
1.创建进程方式1
from multiprocessing import Process import time # 1.定义一个任务 def task(name): print(f'{name}的任务开始执行') time.sleep(1) print(f'{name}的任务结束执行') if __name__ == '__main__': # target = 执行函数的地址 args= 是传入函数的变量元组形式 p = Process(target=task,args=('abc0',)) # 向操作系统提交创建进程的任务 p.start() print('主进程') '''# 先执行主进程,在创建的字进程执行 主进程 abc0的任务开始执行 abc0的任务结束执行 '''
2.创建进程方式2
自定义一个类,并继承Process
# 1.自定义一个类,并继承Process class MyProcess(Process): # 父类的方法 def run(self): print('任务开始执行...') time.sleep(1) print('任务结束执行...') if __name__ == '__main__': p = MyProcess() p.start() # 创建子进程 print('主进程') ''' 主进程 任务开始执行... 任务结束执行... '''
5.进程之间的数据相互隔离
主进程子进程会产生各自的名称空间
from multiprocessing import Process x = 100 def func(): global x x = 20 if __name__ == '__main__': p = Process(target= func) p.start() print(x) print('主程序') '''x = 100 '''
同步和异步
指的是提交任务的方式
同步
若有两个任务需要提交,在提交第一个任务时,必须等待该任务执行结束后,才能继续提交并执行第二个任务
同步,是所有的操作都做完,才返回给用户结果
异步
指的是若有两个任务需要提交,在提交第一个任务时,不需要原地等待,立即可以提交并执行第二个任务
异步,不用等所有操作等做完,就响应用户请求
阻塞与非阻塞
阻塞
阻塞态,遇到IO一定会阻塞
非阻塞
就绪态,运行态
面试题
同步和异步,阻塞与非阻塞是同一个概念么
答:不是同一个概念,不能混为一谈. IO操作与代码的执行
最大化提高CPU的使用率提高,尽可能减少io操作