线程是如何靠中断切换的呢

描述

上一次的大合集我们从半导体讲到了逻辑门,再从逻辑门讲到了组合逻辑电路和时序逻辑电路,又紧接着介绍了CPU内核的设计体系,最后以CPU的指令集作为结尾,一个CPU已经颇具雏形。

经过11-19章的更新,我们又介绍了线程和进程,处理器的中断和异常、特权模式以及最主要的缓存。我将用更清楚连贯的语言将这些内容重新串讲一次,帮助大家更好地理解,当然这也是大合集的本来初衷。

下面开始。

首先是线程和进程。早期的计算机在一段时间内只能运行一段代码,比如计算导弹轨迹,计算完了出结果就好了。这也是计算机最本来最初级的用法。但是随着计算机不断发展,尤其是人民生活水平的不断提高,计算机这样的用法实在是有些过于枯燥了。比如我想边用计算机听歌的同时打下这段文字,就需要计算机能同时做两件事,于是人们就发明了线程,而线程之间通过少量的必要的沟通可以组合形成一个进程,也就是我们通常意义上的应用程序。比如说音乐播放器中,音乐的播放是一个线程,用户的操作界面是另外一个线程,两个线程合起来构成了音乐播放器。当然,一个应用程序(进程)也可以只有一个线程。每个线程包括系统线程都被划定了一个空间,并且高权限线程(系统线程)能访问低权限线程(应用程序)的空间,低权限线程只能访问属于自己的空间,不然病毒线程将大行其道。所以线程的一个基本属性需要在CPU中被明确记录的是权限等级。

对于计算机系统或者CPU来说,越值得信赖的线程的权限等级是越高的。什么是越值得信赖的线程呢?计算机本身的操作系统肯定是值得信赖的,毕竟如果连操作系统都不能信赖,还有什么值得信赖?不过操作系统虽然值得信赖,但本身肯定多多少少存在一些Bug,不然Windows也不会天天蓝屏了,但是对于CPU来讲,操作系统即使有无心的错误,但肯定不会是有害的错误。

那么权限等级能决定什么呢?能决定这个线程能访问哪些内容。

话说回来,早期的那个计算导弹的程序在现在看来就可以算是一个线程。而具体是如何做到并行处理的呢?看过三体的同学应该都知道三体人是怎么用一颗智子封锁地球科技的,靠的就是智子光速来回穿梭干扰在位于地球各处的高能粒子对撞机。因为智子速度太快了,所以只需要一颗就能封锁整个地球的科技。CPU也是同理,随着CPU性能的提升,它也可以快速来回切换并处理不同的线程,底层都是串行的,但给我们的感觉却是并行的。

当然随着科技的进一步发展,CPU的核心数早已从单核心变成了多核心,甚至在一些服务器里我们还能见到多CPU的主板,所以依靠多个CPU核心,现在也能实现真正意义上的并行,不过线程数总是多于CPU核心数,因此线程的切换即使到了今天也是一直在用的。

那么线程是如何切换的呢?最常见的就是靠中断了。中断顾名思义,做到中间的时候被打断了,有更高优先级的人物需要处理。什么被打断了?当前执行的线程被打断了。被什么打断了?不好说,有可能是定时时钟,有可能是你敲击的键盘或你移动的鼠标,有可能是某一个线程自己发出来的“软中断”。为什么要有中断?就我个人理解,中断是人与电脑进行实时交互的窗口,没有中断就像你没有鼠标和键盘,啥也做不了。但是中断并不是只有人可以用,计算机本身也能用,只要是优先级更高的任务需要介入就可以用。

所以线程是如何靠中断切换的呢?

第一个方法,我称之为被动切换。系统里的计时器会对该线程计时,时间差不多了(大概是5ms左右,看系统设定)就该把CPU让位置出来给另一个线程了。具体过程是,当系统时钟达到设定的时间时,向CPU发送一个中断信号,CPU将现在线程的上下文作为栈保存在内存中,暂时储存起来,同时将pc寄存器跳转到内存中存有中断服务例程的入口处,执行中断服务例程的程序,程序会查找得知中断来源(这一步在高级的CPU上可以用硬件实现从而省略软件查找的过程),进而跳转到系统调度线程,这个线程会根据执行情况将一个新线程调度到CPU上执行,自己则退隐。从而实现线程的切换。

第二个办法,我称之为主动切换。当本线程没事干了,或者说在等另一边的结果,那么这个时候就会执行一个软中断,自觉地把线程让出来(要是不自觉就没办法了),流程和上面一致,只不过中断源不再是时钟了,而是线程本身,称之为软(软件)中断。

还有一种办法不是靠中断切换线程,也可以并行处理的一种技术叫做超线程技术。这个技术是Intel率先提出来的,他们声称增加5%的晶体管数量可以提升20%的性能。

可以理解为如果当前线程没事干,而且这个线程“不自觉退出”,那么硬件直接介入让另外一个线程运行。与上面靠中断的第二种方法不同的是,这种切换是CPU硬件自发的,操控粒度可以更细(前者只能在软件层面判断是否会有空闲情况发生,后者则能在硬件层面监控,硬件发生堵塞情况软件是无法知道的),智能程度会更高,线程切换的过程消耗也会更小。如此一来,CPU可以在本该空等的地方择机执行另外一个线程的指令,实现了时间管理,缩短了两个程序执行的总体时间。

上文中提到的线程切换技术中除了第一种被时钟叫停的以外,基本都是太闲了主动让位或者被让位的。那么为什么会出现线程太闲的情况呢?因为他们在等。等的可能是远方服务器的响应,可能是用户的输入,可能是内存数据的返回……前两种无关性能,解决不了也不用解决,但是等内存可不行,所以介于CPU核心和内存之间的缓存出现了。

缓存读写速度要比内存快,因为缓存采用的是SRAM存储器内建在CPU上,而内存采用的是DRAM。前者可以达到很高的读取速度但是面积占用比较大因此容量上不去,在几M容量就止步了。后者读取速度慢且每次读取后都要刷新电容,但面积占用小,因此容量可以达到好几个G甚至几百几千个G。

那为什么缓存能提高CPU性能呢?程序运行具有一定规律——顺序和反复性,即顺序执行和循环执行。对于顺序执行,可以采取预读策略。即将后面的程序一并读取至缓存中,减少内存读取次数(注意CPU的读指令并没有减少,只是内存响应次数少了)。缓存行是缓存的基本单位,目前主流缓存行大小是64字节因为内存一次读操作是64字节,而64位CPU对数据的读取是8字节即64bit,因此若CPU要读的八字节落入某一缓存行中,该缓存行的内容将会全部从内存中被读取到缓存中,接下来的程序也被这次读写一并带到了缓存中去。对于循环执行,则正是缓存的强项,之前访问过的程序都存储在缓存中,再次读取时,直接可以从缓存而不是从内存中读取,大大提高了运行效率。

缓存又有分为一级缓存、二级缓存等等。他们的速度也有所不同,从一级缓存以后读取速度依次降低。为什么呢?虽然都是采用的SRAM存储器,但是数据检索需要时间,数据存储量大的三级缓存找的时间就比数据存储量小的一级缓存找的时间久。如果把内存比作图书馆的书架,那么缓存就像是CPU面前的一张桌子。给你地址让你去找CPU想要的数据,如果你是在书架上找,你可以很清楚这个数据放在哪一行哪一列,如果恰好你运动速度是光速的话,那么你总能在一个确定的时间内拿到CPU想要的数据。可是缓存就不一样了,书就在你面前,还乱糟糟的,你需要翻阅查看地址是否对应上了。因此桌子越大,你找得也就越慢。

就没有别的办法了吗?当然有。桌子乱可以整理整理嘛。比如规定一下,第一书架的书只能放在桌子上的A区,第二书架放B区……以此类推。这样一来,找的人便会方便很多,放的人也没有什么困难。

举个例子,假设内存可以被划分成四个缓存块(即内存大小是缓存大小的四倍),记为00,01,10,11四块。每个缓存块又可以划分成四个缓存行,记为00,01,10,11四行。结合起来,最上面缓存块的最上面的缓存行就可以写成0000,则这个部分的数据应该存在于缓存中的第一个缓存行的位置即00位置。如果1000号缓存行需要写入,那么就要把0000号缓存行擦除再写入,不能存储在缓存中别的地方即使还有空间存放。


审核编辑:刘清


 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分