第二十八天:进程
操作系统发展史
穿孔卡片
一个机房只能用一个卡带,一次只能被一个人使用
缺点:cpu利用率极低
联机批处理
支持多用户去使用一个机房
脱机批处理
高速磁盘:提高了处理速度
优点:提高了使用率
多道技术
单道:
使用是串行,基于单核cpu,一次只能执行一个软件,一个程序结束之后才能执行下一个程序
多道
cpu执行的同时,去加载其他的程序
空间上的复用:一个cpu可以提供给多个程序使用,公用内存条一个,每个进程都有各自独立的内存空间,互不干扰,物理级别的隔离d
时间上的复用:切换+保存状态
切换:若cpu遇到I/O操作,会立即将当前执行的程序cpu使用权断开切换给其他用户
提高了cpu的使用率
若一个cpu程序的使用时间过长,会立即将切换使用权
导致程序的执行率降低。
保存状态:当再次回到本程序的执行时,不需要重新加载
并发与并行
并发:
指的是看起来像在同时运行
相当于多个程序不不停的切换+保存状态
并行:
指的是真正意义上的同时运行
基于多核,同时执行多个程序
进程
程序:指的是一堆代码
进程:指的是一堆代码运行的过程
进程调度
-
先来先服务
若a程序先来,则先占用cpu
缺点:必须程序B必须等待A使用完cpu后才能使用
-
短作业优先
谁的用时短,谁优先使用cpu
缺点:若程序A使用时间最长,后面还有N个运行时间短的程序,则A要等所有程序结束后才执行
-
时间轮转
在一秒种,加载了N个用户,要将一秒等分位N个时间片
-
分级反馈队列
将执行优先分为多个级别。
越往下的优先级越低
程序运行时的三种状态
就绪
所有进程创建时都会进入就绪态
运行
程序调度后,进入运行态
阻塞
凡是遇到I/O操作的进程都会进入阻塞态,若I/O结束,必须重新进入就绪态
同步和异步
指的时提交任务的方式。
同步
若有两个任务需要提交,在提交第个任务时,必须等待该任务执行结束后,才能继续提交并执行第二个任务
异步
若有两个任务提交,在提交第一个任务时没不需要原地等待,立即可以执行第二个任务
阻塞和非阻塞
阻塞
阻塞态。遇到I/O一定会阻塞
非阻塞
就绪态
运行态
同步和异步,阻塞和非阻塞是同一个概念吗?
不是,不能混为一谈!
想要cpu利用率最大化,需要异步提交,和非阻塞态。但是一个程序基本上都会有I/O操作,所以只能尽可能减少不必要的I/O操作
创建进程的 两种方式
定义一个任务
def task(name):
print(f'{name}开始执行')
time.sleep(1)
print(f'{name}的任务已经结束')
# 在windows下这里必须使用这种形式运行,不然会报错
if __name__ == '__main__':
p = Process(target=task, args=('lk',))
p.start()
print('主进程')
定义一个类,并继承Process
# 自定义个类,并继承Process
class MyProcess(Process):
def run(self):
print('开始执行子进程')
time.sleep(1)
print('任务结束子进程')
if __name__ == '__main__':
p = MyProcess()
p.start()
print('主进程结束')
join方法
让子进程结束后再结束父进程
join方法要写在start的下面,因为start的作用是开启一个子进程
def task(name):
print(f'{name}开始执行')
time.sleep(1)
print(f'{name}的任务已经结束')
# 在windows下这里必须使用这种形式运行,不然会报错
if __name__ == '__main__':
p = Process(target=task, args=('lk',))
p.start()
p.join()
print('主进程结束')
进程之间数据是相互隔离的
from multiprocessing import Process
x = 100
def func():
global x
x = 200
if __name__ == '__main__':
p = Process(target=func)
p.start()
print(x)
print('主进程')
进程的属性关系
current_process().pid:获取子进程号
os.getpid():获取主进程号
os.ppid()获取主主进程进程号
进程号都是随机分配的
cmd中查看进程:tasklist |finddstr 进程号
进程号回收的两种条件
- join可以回收子进程与主进程
- 之进程正常结束,子进程和主进程也会被正常回收
.is_alive()判断子进程是否存活,返回布尔值
.terminate()直接告诉操作系统,杀掉子进程
僵尸进程与孤儿进程
僵尸进程
指的是子进程已经结束,但是PID号还是存在,未被销毁
缺点:占用PID号,占用操作系统资源
孤儿进程
指的是子进程还在实行,但父进程意外结束。
操作系统提供一个福利院,帮你回收没有父进程的子进程。
守护进程
指的是主进程结束后,该进程产生的所有子进程都跟着结束,并回收
.deamon()