本文引用图片均来自 李治军: 操作系统32讲
线程
上一篇文章讲到多进程是操作系统的基本图像,多个进程交替执行。其实进程内部还有更小的工作单元:线程
进程内部的多线程和操作系统中的多进程很像,它们也是交替执行,进程有PCB线程则有TCB(Thread Control Block)。线程共享同一个进程的资源(映射表, 数据等),相比进程切换开销小得多
多线程有什么用呢?其实和多进程类似,多进程能让用户同时干不同的事,多线程则能让进程同时干不同的事
以浏览器为例,打开一个网页它可以创建多个线程,有的负责下载数据,有的渲染背景有的则负责展示数据
线程交替
进程和线程都是交替执行但交替控制者不同,进程交替由操作系统控制而线程交替则由用户控制
进程交替主要是进程由于时间片耗尽或读写磁盘阻塞等原因被操作系统换下,本文讲的用户级线程其实对于操作系统来说是透明的,也就是操作系统只能看到进程在执行,不知道进程内部有线程,所以操作系统无法主动切换用户级线程
如果某个线程阻塞了(如读写磁盘),那么操作系统会认为该进程阻塞了从而将CPU分配给其他进程,导致进程内所有线程都被阻塞
用户控制交替最大的好处就是可以控制线程的执行,线程什么时候启动、暂停和结束都由用户决定灵活性很大
以下图浏览器中的线程为例,GetData线程下载了文本就主动让出控制权让Show线程展示,Show展示完了再让出控制权让GetData继续去下载图片
线程虽然共享进程资源,但它们也有自己的私有资源包括栈和PC等,线程让出控制权是使用Yield函数,和进程切换类似线程切换也涉及保存上下文,看下面的例子
1. 线程1执行A,B函数,栈顶指向992处,线程2执行C,D函数,栈顶指向1992处
2. 线程1在A函数中调用B函数,104(A函数的下一条指令地址)入栈
3. 线程1在B函数中调用Yield函数让出控制权,204(B函数的下一条指令地址)入栈,此时栈顶指向1000处
4. 此时切换到线程2,从TCB中取出上下文(栈,PC等)完成切换
5. 线程2在C函数中调用D函数,304(C函数的下一条指令地址)入栈
6. 线程2在D函数中调用Yield函数让出控制权,404(D函数的下一条指令地址)入栈,此时栈顶指向2000处
7. 此时切换到线程1,从TCB中取出上下文(栈,PC等)完成切换
8. 线程1栈顶退栈得到下一条指令地址204,继续执行B函数,B函数结束后继续退栈得到104返回A函数...