对进程以及创建进程的理解
【一】进程和程序
【1】什么是进程?
- 进程就是正在运行的程序
【2】谁来执行进程?
- cpu
【3】进程和程序的区别?
- 程序是存储再硬盘里面的一堆代码和数据
- 进程是正在运行的程序
【二】进程调度问题
- 有一个算法叫做任务调度算法
- 就像是一个非常聪明的调度员,在计算机系统中负责安排和管理各种任务(比如程序或进程)的执行顺序。想象一下,你在一个忙碌的餐厅里,服务员需要决定先给哪个顾客上菜,这个过程就像是任务调度。
- 在计算机中,有很多任务都想要使用CPU(就像顾客想要吃饭一样),但CPU的能力有限,不能同时处理所有任务。因此,任务调度算法的作用就是决定哪个任务先执行,哪个后执行。这样的安排既要公平,又要高效,确保每个任务都能得到合理的处理时间,同时让整个系统运行得更流畅。
- 先来先服务(FCFS, First-Come, First-Served):这个算法很简单,谁先来,就先服务谁。就像排队买票,先来的人先买。
- 短作业优先(SJF, Shortest Job First):这个算法会优先处理那些需要时间最短的任务。想象一下,如果你是厨师,你可能会先做那些更快做好的菜。
- 时间片轮转(RR, Round Robin):这个算法把时间分成若干小块,每个任务轮流使用一小块时间。就像玩游戏时,每个人轮流玩一会儿。
- 优先级调度:在这个算法中,每个任务都有一个优先级,优先级高的任务先执行。这就像是某些VIP顾客可以优先点餐。
【三】串行,并发,并行
【1】介绍
- 串行 (Serial):想象一下,你是一位厨师,在厨房里一次只能做一道菜。你得先做完第一道菜,然后再开始做第二道,接着是第三道,依此类推。每道菜都需要等前一道做完才能开始。这就是串行,任务一个接一个地执行,前一个完成后才开始下一个。
- 并发 (Concurrency):现在假设你仍然是那位厨师,但这次你在做一道菜的同时,可以监控正在炖的汤,并且偶尔还可以和顾客聊天。虽然你仍然一次只能专注于一件事,但你可以在不同任务之间迅速切换,给人一种同时处理多件事的感觉。这就是并发,多个任务交替进行,但在任意时刻实际上只有一个任务在执行。
- 并行 (Parallelism):最后,想象你现在有一个团队,团队里有几位厨师。这次,当你在准备一道菜时,你的同事可以同时炖汤,另一个同事则可以和顾客聊天。这样,几件事情真正地在同一时间同时进行。这就是并行,多个任务在同一时刻同时发生,通常需要多个处理单元(比如多个厨师)。
【2】总结
- 串行:一个接一个,按顺序执行。
- 并发:一次只能做一件事,但可以迅速在多个任务之间切换。
- 并行:多件事情同时进行。
- 核心:多道技术就是:cpu切换和保存状态
【四】同步/异步/阻塞/非阻塞(重要)
【1】介绍
- 同步 (Synchronous):想象你去咖啡店点了一杯咖啡。在咖啡没做好之前,你就站在那里等,什么其他事都不做,直到咖啡做好,你拿到咖啡后再去做其他事情。这就是同步,你的行为(等待咖啡)和咖啡制作过程是一致对应的。
- 异步 (Asynchronous):这次同样是在咖啡店点咖啡,但是在咖啡制作的同时,你不用站在那里等。你可以去做一些其他的事情,比如看书或者刷手机。当咖啡做好了,店员会叫你来拿。这就是异步,你的行为(做其他事情)和咖啡制作过程是分开的,不用一直等待咖啡制作完成。
- 阻塞 (Blocking):再想象一下,你在餐馆点了一道菜,然后就坐在桌子旁边等,直到菜做好。在这期间,你不做任何事情,只是等待。这就是阻塞,你的等待阻止了你做其他事情。
- 非阻塞 (Non-blocking):这次在餐馆点餐后,你不是一直坐在那等,而是去玩手机、看书或跟朋友聊天。尽管你还在等你的菜,但你没有被这个等待过程所阻塞,你可以同时做其他事情。这就是非阻塞,等待某个操作的完成时,你可以同时进行其他操作。
【2】同步 vs 阻塞
- 关注点不同:同步关注的是操作的执行顺序,而阻塞关注的是程序在等待时的行为。
- 应用场景:你可以有同步但非阻塞的操作,例如,同步轮询一个状态标志,直到它改变。同样,也可以有异步但阻塞的操作,例如在多线程应用中使用阻塞队列。
【3】总结
- 同步:在一个操作完成之前,一直等待。
- 异步:提交操作后可以做其他事情,操作完成后会通知你。
- 阻塞:等待(比如输入输出操作)时什么也做不了。
- 非阻塞:等待时还可以做其他事情。
【五】进程的创建和状态
【1】引入
- 进程是计算机中的一个基本概念,它代表了计算机中正在运行的程序。每个进程都有自己的内存空间、数据和执行的代码。我们可以把进程想象成一个工厂里的工作线:它有自己的任务(程序代码),需要的材料(数据),以及工作的空间(内存)。
【2】进程的创建
- 加载: 计算机把程序的代码和所需数据加载到内存中。
- 初始化: 设置进程的初始状态,比如分配一个唯一的标识符(PID)、确定进程优先级、创建进程控制块(PCB)等。
- 执行: 开始执行程序的代码。
- 等待: 在某些情况下,比如等待用户输入或文件读写操作,进程会暂时停止执行。
- 终止: 程序执行完成后,进程会被终止,释放所占用的资源。
【3】进程的三状态
- 阻塞态(阻塞):等待某个事件的完成;
- 就绪态(就绪):等待系统分配处理器以便运行;
- 运行态(运行):占有处理器正在运行;
运行态——>阻塞态:往往是由于等待外设,等待资源分配或等待人工干预而引起的。
阻塞态——>就绪态:则是等待的条件已满足,只需要分配到处理器后就能运行。
就绪态——>运行态:系统按照某种策略选中就绪队列中的一个进程占用处理器,就绪就变成了运行态。
就绪 —操作系统调度—> 运行 —遇到IO操作—> 阻塞 —阻塞状态结束—> 就绪
【六】创建进程的两种方式
- 方法一
# 创建进程 方法一
from multiprocessing import Process # 导入模块中类,用于创建新的进程
import time # 导入time模块,用于在后面的函数中实现等待(休眠)功能。
def func(name):
print(f'{name}任务开始')
time.sleep(3)
print(f'{name}任务结束')
if __name__ == '__main__':
p = Process(target=func, args=('写作业',))
p.start() # 异步提交了一个任务
print('主进程')
- 方法二
# 创建进程 方法二
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.task_name = name
def run(self) -> None:
print(f'{self.task_name}任务开始')
time.sleep(3)
print(f'{self.task_name}任务结束')
if __name__ == '__main__':
p = MyProcess('打游戏')
p.start()
print('主进程')
【七】进程之间的数据是相互隔离的
from multiprocessing import Process
age = 18
def run():
global age
age += 2
print(age)
if __name__ == '__main__':
p = Process(target=run, args=())
p.start() # 20
p.join() # join会使子进程先运行完再运行主进程
print(age) # 18
- 可以看到主进程输出的age依旧是18
- 而经过修改的子进程的age输出的就是20
【八】查看进程ID的两种方法
【1】multiprocessing模块里的current_process方法
from multiprocessing import Process, current_process
import time
def func():
print('我是子进程')
print(f'子进程ID:>>>>{current_process().pid}')
time.sleep(20)
if __name__ == '__main__':
p = Process(target=func)
p.start()
print(f'主进程ID:>>>>{current_process().pid}')
【2】os模块下的getpid方法
- 获取进程ID
from multiprocessing import Process, current_process
import time
from os import getpid
def func():
print('我是子进程')
print(f'子进程ID:>>>>{getpid()}')
time.sleep(20)
if __name__ == '__main__':
p = Process(target=func)
p.start()
print(f'主进程ID:>>>>{getpid()}')
- 获取父ID
from multiprocessing import Process, current_process
import time
from os import getpid, getppid
def func():
print('我是子进程')
print(f'子进程ID:>>>>{getpid()}')
print(f'父进程ID:>>>>{getppid()}')
time.sleep(20)
if __name__ == '__main__':
p = Process(target=func)
p.start()
print(f'主进程ID:>>>>{getpid()}')
'''
主进程ID:>>>>26316
我是子进程
子进程ID:>>>>20696
父进程ID:>>>>26316
'''
【九】其他进程操作方法补充
【1】杀死进程(Process类里的terminate方法)
from multiprocessing import Process, current_process
import time
def func():
print('我是子进程')
if __name__ == '__main__':
p = Process(target=func)
p.start()
time.sleep(2)
p.terminate()
time.sleep(2)
【2】判断进程是否存货(Process类里面的is_alive方法)
from multiprocessing import Process, current_process
import time
def func():
print('我是子进程')
if __name__ == '__main__':
p = Process(target=func)
p.start()
print(p.is_alive())
time.sleep(2)
p.terminate()
time.sleep(2)
print(p.is_alive())
'''
True
我是子进程
False
'''