# 生成器到协程

# 任务上下文

在经典的线程模型中,每个线程都有一个独立的执行流,只能执行一个任务。如果一个程序需要同时处理多个任务,可以借助 多进程 或者 多线程 技术。假设一个站点需要同时服务多个客户端连接,可以为每个连接创建一个独立的线程进行处理。

不管线程还是进程,切换时都会带来巨大的开销:用户态/内核态切换、执行上下文保存和恢复、CPU缓存刷新等等。因此,用线程或进程来驱动小任务的执行,显然不是一个理想的选择。

要实现多任务执行系统,一个程序想要同时处理多个任务,其关键之处在于必须提供一种能够记录任务执行进度的机制。

在经典线程模型中,这个机制由 CPU 提供:

程序内存空间分为代码、数据、堆以及栈等多个段,CPU 中的 CS 寄存器指向代码段,SS 寄存器指向栈段。当程序任务(线程)执行时,IP 寄存器指向代码段中当前正被执行的指令,BP 寄存器指向当前栈帧,SP 寄存器则指向栈顶。

有了 IP 寄存器,CPU 可以取出需要执行的下一条指令;有了 BP 寄存器,当函数调用结束时,CPU 可以回到调用者继续执行。因此,CPU 寄存器与内存地址空间一起构成了任务执行上下文,记录着任务执行进度。当任务切换时,操作系统先将 CPU 当前寄存器保存到内存,然后恢复待执行任务的寄存器。

image

但是注意到Python中的生成器是可以记住自己的执行进度的,因此可以考虑使用生成器来实现任务执行流。 同时由于生成器在用户态运行,切换成本比线程或进程小很多,因此是组织微型任务的理想手段。