一、进程基础
冯诺依曼体系:
程序和系统:一个系统一般由多个程序构成。如:Win10系统由进程管理程序、内存管理程序、N个驱动程序等构成。
操作系统的作用:与硬件交互,为用户程序提供安全、稳定的执行环境,提供大量的API供用户程序使用。
任务:打开某个软件、浏览网页、下载电影、听音乐、玩游戏……每个应用程序被称为一个任务。
单任务:只能有一个任务在进行(DOS系统)
多任务:可以有多个任务同时进行(Win10系统)
CPU时间片:程序的执行依赖于CPU,CPU把自己进行时间上的分割,每个程序轮流占用CPU。时间片一般是切换所需时间的100倍。
0.01us 运行 A 0.02us 运行B 时间片轮转
单核: 同一时间,只能有一个程序 在使用CPU
分时操作系统:以时间片轮转的方式,让一台计算机为多个终端服务。 (多用户)
进程:应用程序的动态执行过程。(Process:(为达到某一目标的)过程;进程;流程、过程、步骤;)
- 网易云音乐 (软件)
- cloudmusic.exe(进程)
- 过程: 启动 -> 软件代码要加载到内存--> CPU为进程建立“档案” --> 等CPU时间片 -- > 退出
- 软件只有运行才能生成进程
- 1个软件可以生成1~n个进程
二、进程的状态:运行、等待、就绪
- PCB: 进程控制块(PCB Process Control Block),是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构,每 一个进程均有一个PCB
- 创建状态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无 法满足,就无法被调度运行,把此时进程所处状态称为创建状态
- 就绪状态:Ready to run。创建进程后,进程进入就绪状态(即进程被加载到主内存中)这里的进程已经准备好运行,正在等待获取执行它的CPU时间。准备由CPU执行的进程在队列中维护以备处理。
- 执行状态:进程由CPU选择执行,进程中的指令由任何一个可用的CPU核心执行。
- 阻塞状态:每当进程请求访问I/O或需要用户输入,它将进入阻塞或等待状态。进程继续在主内存中等待,不需要CPU。一旦I/O操作完成,进程将进入就绪状态。
- 终止状态:进程被终止,PCB也被删除。
操作系统管理进程:分配内存给进程,分配CPU时间片给进程,存储进程信息(使用PID标识进程,为进程设置优先级,记录进程状态,记录I/O状态等
如何人为地改变进程的状态:可以通过信号修改进程的状态。taskkill /f /PID 8899 taskkill /f /t /im Typora.exe 杀程序
三、创建并执行进程
在Python中,执行一个Python脚本,就会创建一个进程。
可以用os.getpid()获得进程的PID
如何创建2个进程? multiprocessing.Process创建进程
关于daemon:
- 设置daemon = True,主进程执行完,不会等待该进程
- 设置daemon = False,主进程执行完,会等待该进程执行完再退出
关于join:
- p1.json()
- 主进程会等p1执行完再执行剩下的代码。
import os import time from multiprocessing import Process def cloudmusic(): """模拟网易云音乐的进程""" for i in range(5): print(f"子进程{os.getpid()}正则播放 无人之岛...") time.sleep(1) def lol(): """模拟lol进程""" for i in range(8): print(f"子进程{os.getpid()}游戏中,请勿打扰...") time.sleep(1) def process_test(): start_time = time.time() # 创建网易云音乐进程 # 在主进程中通过Process类创建的进程对象就是子进程 p1 = Process(target=cloudmusic) p2 = Process(target=lol) # 设置daemon = True,主进程执行完,不会等待该进程 # 设置daemon = False,主进程执行完,会等待该进程执行完再退出 p1.daemon = True p2.daemon = False print(f"我是主进程,我的进程id是{os.getpid()}") p1.start() # 启动子进程p1 p2.start() # 启动子进程p2 p1.join() # p2.join() end_time = time.time() print(end_time - start_time) # 这是主进程中最后1行代码,运行完,主进程结束 if __name__ == '__main__': process_test() # start_time = time.time() # lol() # cloudmusic() # end_time = time.time() # print(end_time - start_time)
四、进程的全局变量
每创建一个进程,CPU都会单独分配资源
所以,多个进程不会共享全局变量
from multiprocessing import Process result = 0 def work01(): global result result += 1 print(f'work01中result值是{result}') def work02(): global result result += 1 print(f'work02中result值是{result}') def main(): work01() work02() print(result) def process_test(): p1 = Process(target=work01) p2 = Process(target=work02) p1.start() p2.start() p1.join() p2.join() if __name__ == '__main__': process_test() print(f'主进程中result的值是:{result}') ''' work01中result值是1 work02中result值是1 主进程中result的值是:0 '''
五、多进程中使用队列共享数据
多进程中如何使用队列共享数据?
答: 多个进程共享主进程中创建的队列即可。主进程创建队列,然后把队列当做参数传给每个子进程即可。
from multiprocessing import Process, Queue def work01(q): print(id(q)) r = q.get() r += 1 q.put(r) print(f'work01中q值是{r}') def work02(q): print(id(q)) r = q.get() r += 1 q.put(r) print(f'work02中q值是{r}') def process_test(): q = Queue() q.put(0) p1 = Process(target=work01, args=(q,)) p2 = Process(target=work02, args=(q,)) p1.start() p2.start() p1.join() p2.join() print(f'主进程中q的值是:{q.get()}') if __name__ == '__main__': process_test()
六、自定义进程类
import multiprocessing import time class MyProcess(multiprocessing.Process): def __init__(self,user): super(MyProcess, self).__init__() self.user = user def run(self): """进程启动的时候会调用此方法""" for i in range(3): time.sleep(1) print(f'{self.user}正在学习Python...') if __name__ == '__main__': p1 = MyProcess(user='小样儿') p2 = MyProcess(user='乐乐') p1.start() p2.start() ''' 小样儿正在学习Python... 乐乐正在学习Python... 小样儿正在学习Python... 乐乐正在学习Python... 小样儿正在学习Python... 乐乐正在学习Python... '''