0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

冬至配饺子 来源:天奇工作室 作者:LRC 2022-08-02 18:19 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

上一次的大合集我们从半导体讲到了逻辑门,再从逻辑门讲到了组合逻辑电路和时序逻辑电路,又紧接着介绍了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号缓存行擦除再写入,不能存储在缓存中别的地方即使还有空间存放。


审核编辑:刘清


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

    关注

    68

    文章

    20150

    浏览量

    247285
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11219

    浏览量

    222978
  • 中断
    +关注

    关注

    5

    文章

    913

    浏览量

    43566
  • 计时器
    +关注

    关注

    1

    文章

    434

    浏览量

    34876
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    线程的系统

    线程系统的事件响应也是在中断中完成的,但事件的处理是在线程中完成的。在多线程系统中,线程中断
    发表于 12-08 07:55

    Linux多线程对比单线程的优势

    ,而单线程则需要通过进程间通信来实现。「上下文切换开销小」:线程的上下文切换比进程小,因为它们共享相同的地址空间。「提高响应性」:多线程可以
    发表于 12-01 06:11

    线程问题,线程已经创建成功了,为什么线程调用的函数不会运行

    我这个线程创建成功了,为啥ai_thread_entry()函数不运行? void airun_thread() { /* 创建 serial 线程 */ rt_thread_t
    发表于 10-10 08:02

    rtt中线程切换,当执行完rt_schedule,为什么不立即进入下个线程开始执行

    感觉是切换完了,也得等到下一个时钟中断产生后才能执行?
    发表于 10-10 07:05

    rtt中建两个线程a和b,怎么确保线程a执行完立刻切到线程b?

    怎么获取从线程开始切换切换完成用的总的CPU时钟节拍数量?
    发表于 10-10 06:37

    切换线程中断被屏蔽怎么解决?

    退出,已经切换到main线程,但是发现此时中断是被屏蔽的。 跟代码发现rt_schedule最后切换线程时是先调用rt_hw_context
    发表于 09-29 07:48

    ulog输出异常-中断线程打印冲突怎么解决?

    逻辑:can收到数据后,can中断打印test,并把数据放到消息队列,main函数的消息队列打印消息内容 问题:只要can中断中有test打印的代码,整个串口就会卡死; 中断中无test打印的代码
    发表于 09-28 11:44

    CAN发送只能使用中断或者DMA,为什么?

    ,RT_DEVICE_FLAG_INT_RX|RT_DEVICE_FLAG_INT_TX ); 我明明可以选择一个定时器,时间到了之后直接手动发送就完成了,配置成中断发送模式涉及线程切换势必要浪费不必要的时间,使用DMA又会
    发表于 09-25 07:19

    rtthread在线程执行过程中,被中断打断后进入中断处理时,是否有保护FPU的状态?

    会先进行一些补偿校正计算, 然后在接收特定消息后在中断中进行切换, 新下传的幅值相同但是按0.1v递增;频率固定为50Hz,相位固定0°,-120°,120°,所有数据*10000放大, 其中
    发表于 09-24 07:50

    使用串口485线程,发现收到数据回调函数一直没有运行是怎么回事?

    ,引脚PB6和PB7,串口配置没有问题,开机可以正常打印,如下图。 发送485指令,通过打印和debug发现信号量一直为-2,且收到数据会自动进入串口中断函数,不会进入我写的线程中接收。 我这边硬件上有485自动引脚切换
    发表于 09-18 06:03

    中断发送信号量不能释放等待信号量的线程是怎么回事?

    MCU为stm32f407vgt6,rt-thread的版本为4.0.3。 代码如下: /* 接收数据回调函数,该函数会在uart中断例程中调用*/ static rt_err_t
    发表于 09-10 06:28

    深度剖析 RT-Thread 线程调度流程

    rt_system_scheduler_start:调度系统第一个线程rt_hw_context_switch_to:初始化上下文切换环境,触发PendSV异常first_thread:系统中优先级最高
    的头像 发表于 06-25 18:24 1450次阅读
    深度剖析 RT-Thread <b class='flag-5'>线程</b>调度流程

    进程、线程、协程傻傻分不清?一文带你彻底扒光它们的\"底裤\"!

    它们就像程序界的「三国演义」: 进程:曹魏政权(独占资源,稳如老狗) 线程:孙刘联军(共享资源,相爱相杀) 协程:诸葛亮北伐(一人带十军,的是「空城计」) 第一章:进程——程序界的「独狼」 定义
    发表于 03-26 09:27

    程序中断的100种写法

    事件。 9. 中断与多线程 线程中断:在多线程环境中,通过线程间通信机制实现
    发表于 01-28 08:25

    AN-1420:利用数字锁相环(DPLL)实现相位增建和无中断切换

    电子发烧友网站提供《AN-1420:利用数字锁相环(DPLL)实现相位增建和无中断切换.pdf》资料免费下载
    发表于 01-13 14:07 0次下载
    AN-1420:利用数字锁相环(DPLL)实现相位增建和无<b class='flag-5'>中断</b><b class='flag-5'>切换</b>