1. 多任务概述
- 多任务 即操作系统中可以同时运行多个任务。
- 计算机原理
- CPU:计算机硬件的核心部件,用于对任务进行执行运算。
- 操作系统用CPU执行任务
- CPU轮询机制:CPU都在多个任务之间快速的切换执行,切换速度在微少级别
- 多核CPU
- 并发:多个任务如果被分配给了一个CPU内核,多任务之间是并发关系,多个任务之间并不是真正的“同时”
- 并行:多个任务如果被分配给了不同的CPU内核,多任务之间执行就是并行关系
- 多任务编程
- 即一个程序中编写多个任务,在程序运行时让这多个任务一起运行。
- 实现多任务编程的方法
- 多任务意义
- 提高任务之间的配合,根据运行情况进行任务创建
- 充分利用计算机资源,提高任务执行效率
- 在任务中有阻塞时并行并发都能提高效率
2. 进程(Process)
- 进程概述
- 定义:程序在计算中的一次执行过程
- 程序是一个可执行的文件,是静态的占有磁盘。
- 进程是一个动态的过程描述,占有计算机运算资源 ,有一定的生命周期
- 进程状态
- 三态
- 就绪态:进程具备执行条件,等待系统调度分配CPU资源
- 运行态:进程占有CPU正在运行
- 等待态:进程阻塞等待,此时会让出CPU
- 五态(增加新建和终止)
- 新建:创建一个进程,获取资源的过程
- 终止:进程结束,释放资源的过程
- 进程命令
- 查看进程信息
ps -aux
- USER : 进程的创建者
- PID : 操作系统分配给进程的编号,大于0的整数,系统中每个进程的PID都不重复。PID也是重要的区分进程的标志。
- %CPU,%MEM : 占有的CPU和内存
- STAT : 进程状态信息,S I 表示阻塞状态 ,R 表示就绪状态或者运行状态
- START : 进程启动时间
- COMMAND : 通过什么程序启动的进程
- 进程树结构
pstree
- 父子进程:在Linux操作系统中,进程形成树形关系,任务上一级进程是下一级的父进程,下一级进程是上一级的子进程。
- 多进程编程
- 使用模块:multiprocessing
- 创建流程
- 【1】 将需要新进程执行的事件封装为函数
- 【2】 通过模块的Process类创建进程对象,关联函数
- 【3】 通过进程对象调用start启动进程
- 新版windows MACOS进程创建(防止无穷尽的创建进程)
if __name__ = "__main__":
process = mp.Process(target = fun)
process.start()
process.join()
3. 多进程编程
- 使用模块:multiprocessing
- 创建流程【1】将需新进程执行的事件封装为函数【2】通过模块的Process类创建进程对象,关联函数【3】通过进程对象调用start启动进程
- 主要类和函数使用Process()
功能:创建进程对象
参数:target绑定要执行的目标函数
args 元组,用于给target函数位置传参
kwargs 字典,给target函数键值传参
daemon bool值,让子进程随父进程退出p.start()
功能:启动进程注意:启动进程此时target绑定函数开始执行,该函数作为新进程执行内容,此时进程真正被创建p.join([timeout])
功能:阻塞等待子进程退出
参数:最长等待时间 - 进程执行现象理解
- 新的进程是原有子进程,子进程复制父进程全部内存空间代码段,一个进程可以创建多个子进程。
- 子进程只执行指定函数,其余内容均是父进程执行内容,但是子进程也拥有其他父进程资源。
- 各个进程在执行上互不影响,也没有先后顺序关系。
- 进程创建后,各个进程空间独立,相互没有影响
- multiprocessing创建的子进程中无法使用标准输入(无法使用input)
- 进程处理细节
- 进程相关函数os.getpid()
功能:获取一个进程的PID值
返回值:返回当前进程的PIDos.getppid()
功能:获取父进程的PID号
返回值:返回父进程PIDsys.exit(info)
功能:退出进程
参数:字符串 表示退出时打印内容
- 孤儿进程和僵尸进程
- 孤儿进程:父进程先于子进程退出时,子进程会成为孤儿进程,孤儿进程会被系统自动收养,成为孤儿进程新的父进程,并在孤儿进程退出时释放其资源
- 僵尸进程:子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会成为僵尸进程
- 特点:僵尸进程虽然结束,但会存留部分进程资源在内存中,大量的僵尸进程会浪费系统资源。
- Python模块中建立自动僵尸处理机制,每次创建新进程都进行检查,将之前的僵尸处理掉,而父进程退出前,僵尸也会被自动处理。
示例代码:
"""
编写一个程序,将一个大文件拆分为2个小文件
上半部分拆为一个,下半部分一个,按照字节大小划分
要求: 拆分过程需要同时执行,分别用两个子进程完成
查分完成后,打印提示 "拆分完毕"
提示: os.path.getsize()
file.seek()
难点: 不允许一次读取一半
"""
import multiprocessing
import os
file_source = "./20210111.jpg"
fsize = os.path.getsize(file_source)
# 如果父进程打开文件,子进程直接使用fr,那么
# 父子进程用的是同一个文件偏移量会相互影响
# fr = open(filename,'rb')
# 拆出上半部分
def split_top():
fr = open(file_source, "rb")
fw = open("split_top.jpg", "wb")
fsize01 = fsize // 2 # 要复制n个字节
while fsize01>1024:
fw.write(fr.read(1024))
fsize01 -= 1024
else:
fw.write(fr.read(fsize01))
fr.close()
fw.close()
# 拆出下半部分
def split_bot():
fr = open(file_source, "rb")
fw = open("split_bot.jpg", "wb")
fr.seek(fsize // 2, 0)# 文件偏移量到中间
while True:
data = fr.read(1024)
if not data:
break
fw.write(data)
fr.close()
fw.close()
# 启动函数 创建进程
def main():
jobs = []
for th in [split_top, split_bot]:
p = multiprocessing.Process(target=th)
jobs.append(p)
p.start()
[i.join() for i in jobs] # 等待拆分结束
print("拆分完毕!")
if __name__ == '__main__':
main()