当前位置: 首页 > 科技观察

NFV关键技术:x86架构基础(下)_0

时间:2023-03-12 13:14:34 科技观察

LabsGuide标准服务器技术是实现网络功能虚拟化(NFV)的关键因素。了解x86架构的一些基础知识,有助于理解电信云的关键技术,尤其是掌握虚拟化技术原理和关键优化方案很有必要。本篇沿用上篇文章对x86架构、IO架构等部分的中断和异常进行讲解。1.中断与异常程序的执行往往不像顺序执行那么简单。有些异常和中断会打断程序流的顺序执行,转入完全不同的执行路径。中断为外部设备提供了一种“中断CPU当前任务并响应自身服务”的手段。中断是一个异步事件,通常由I/O设备触发;exception是同步事件,典型的比如处理器在执行某条指令时发现错误等。其实exception的本质就是同步中断。中断一般定义为中断CPU芯片指令执行的事件,该事件对应于CPU芯片内部或外部电路产生的电子信号。中断信号可分为同步中断和异步中断:同步中断,这类中断是由CPU的控制单元在执行一条指令时产生的,在当前指令执行完毕,下一条指令执行之前产生执行。异步中断,这种中断随时由其他硬件设备产生,跟随CPU的时钟信号传递给CPU。对于Intel的CPU,将同步中断称为异常,将异步中断称为中断。通常中断(即异步中断)是由时钟定时器或其他I/O设备产生的,例如键盘接收到按键被按下的信号后产生的中断信号。异常(即同步中断)通常是由编程错误或CPU检测到需要内核处理的异常情况引起的,例如上面提到的PageFaultException(缺页异常)。异常可以由程序通过int或sysenter指令发起。生产。对于Intelx86CPU,它把中断和异常分类如下:中断,即异步中断,中断信息是随着CPU时钟信号传送到CPU内部的。中断分为可屏蔽中断和不可屏蔽中断。可屏蔽中断,所有I/O设备产生的IRQ请求都归类为可屏蔽中断。可屏蔽中断可以有两种状态,屏蔽或不屏蔽,当中断被屏蔽时,中断信号将被相应的控制单元忽略。不可屏蔽中断,即控制单元不能忽略这类中断信号,CPU肯定会收到这类中断,一般对应一些临界事件,比如硬件错误。异常,即同步中断,CPU执行某条指令后产生并接收中断信号。处理器检测到的异常,即当CPU在执行指令时,检测到硬件出现某种异常情况时,就会产生这个信号。此类异常根据产生时保存在内核栈中的EIP寄存器的值(即异常恢复后CPU重新执行的位置)来细分:内核,修正导致异常指令后重新执行,不会导致程序中断或功能异常。此时保存到EIP寄存器的值就是引发异常的指令的地址,所以当异常恢复时会重新执行该指令,比如PageFaultException(缺页异常),当被访问内存地址没有映射到物理内存,当异常产生时,内核会分配一个新的物理内存页并建立映射关系。异常处理后,CPU重新访问地址访问正确的物理内存。traps,当异常发生时,内核栈EIP寄存器保存的地址指向引发异常的指令的下一条指令,即当异常处理返回时,程序会继续执行,而不是重新执行导致异常的指令。x86CPU的硬件虚拟化功能使用了traps和re-simulation。当CPU执行虚拟机指令时,如果执行到敏感指令,就会触发Traps类型的异常,让VMM(VirtualMachineMonitor)对敏感指令进行仿真,然后继续恢复运行虚拟机。Aborts,当发生严重错误时,CPU不能再保证内核栈中EIP寄存器中存储的值就是引起异常的指令的地址。此异常用于报告严重错误,例如硬件错误或内存不一致。异常信号使CPU切换到对应的abort异常处理器,由于无法确认错误,只能结束当前进程。我们在写程序的时候,往往会在容易出错的地方抛出异常,然后为抛出的异常定义执行策略。此类编程产生的异常是由程序主动执行int或int3等指令产生的。CPU以与Traps相同的方式处理这些程序主动产生的异常。这种类型的异常通常称为软件中断(softwareinterrupt)。这种类型的异常有两个主要用途:实现系统调用和通知调试器特定事件。这些异常或中断由0到255之间的数字唯一标识,通常称为中断信号量。对于不可屏蔽中断和异常,对应的中断信号量是固定的,而可屏蔽中断对应的中断信号量可以通过设置中断控制器来改变。2、x86系统的I/O架构计算机处理的任务实际上只有两类:CPU操作和I/O操作。这部分内容是后续学习计算虚拟化中I/O虚拟化的基础。I/O(Input/Output)是CPU访问外部设备的方式。设备通常通过寄存器和设备RAM将自身的功能呈现给CPU,CPU通过读写这些寄存器和RAM完成对设备的访问等操作。x86架构的I/O根据访问方式的不同分为以下两类:2.1PortI/O(以下简称PortI/O)是指通过I/O端口访问设备寄存器。x86有65536个8位I/O端口,编号为0x0~0xFFFF。CPU使用端口号作为设备端口的地址,然后访问设备。这65536个端口构成了64KB的I/O端口地址空间。I/O端口地址空间是独立的,不是线性或物理地址空间的一部分。访问端口需要使用特定的操作命令IN/OUT。这时CPU通过一个特殊的芯片管脚识别这是一个I/O端口访问,所以芯片组知道地址线上的地址是I/O端口号并据此完成。另外,2个或4个连续的8位I/O口可以组成16位或32位I/O口。2.2内存映射I/O(MemoryMapI/O,以下简称MMIO)是指通过内存访问来访问设备寄存器或设备RAM。MMIO占用CPU的物理地址空间。它将设备寄存器或设备RAM映射到物理地址空间中的某个地址,然后使用MOV等内存访问指令访问这个地址来访问映射的设备。MMIO方式访问设备也需要从线性地址到物理地址的转换,但是这个转换过程中的MMIO地址不能缓存到TLB中。MMIO是一种比较常见和高级的I/O访问方式。很多CPU架构没有PortI/O,采用统一的MMIO方式。3、DMA技术直接内存访问(DirectMemoryAccess,以下简称DMA)是所有现代计算机的一个重要特征。DMA允许设备绕过CPU将数据直接复制或读取到内存中。如果CPU用于从设备向内存拷贝数据,CPU会有大量的中断负载。在中断过程中,CPU不能用于其他任务,不利于系统性能的提高。通过DMA,CPU只负责发起传输动作,而传输动作本身是由一个DMA控制器(简称DMAC)来实现和完成的。在实现DMA传输时,DMAC直接控制总线。在DMA传输之前,CPU必须将总线控制权交给DMAC。DMA传输完成后,DMAC立即将总线控制权交还给CPU。一个完整的DMA传输过程的基本流程如下:DMA请求:CPU初始化DMAC,向I/O口发送操作命令,I/O口发出DMA请求。DMA响应:DMAC对DMA请求进行优先级判断和屏蔽判断,然后向总线控制芯片提出总线请求。CPU执行完当前总线周期后,释放总线控制权。此时总线控制芯片发出总线响应,表示DMA请求已响应,并通过DMAC通知I/O口开始DMA传输。DMA传输:DMAC获得总线控制权后,CPU可以暂停或只进行内部操作,DMAC发出读写命令直接控制RAM和I/O口进行DMA传输。DMA结束:当指定的一批数据传输完成后,DMAC释放总线控制并向I/O端口发送结束信号。当I/O口收到结束信号后,停止I/O设备的工作,并向CPU发出中断请求,让CPU执行一段代码检查这次DMA传输操作的正确性,并退出不干涉的状态。可见DMA不需要CPU直接控制传输,也没有像中断处理方式那样保留和恢复场景的过程。通过硬件(DMAC),为RAM和I/O设备开辟了一条直接传输数据的通路,大大提高了CPU的效率。需要注意的是,DMA操作必须访问连续的物理内存。DMA传输的过程如下图所示。DMA技术4.进程、线程和协程4.1什么是进程和线程?什么是流程?用简单的英语来说,进程是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就启动了一个进程。一个进程拥有代码和打开的文件资源、数据资源以及独立的内存空间。什么是线程?线程属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有多个子线程。线程有自己的栈空间。进程图对于操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。进程和线程都由操作系统管理。线程一般有五种状态:初始化>>>可运行>>>运行>>>阻塞>>>销毁。线程不同状态之间的转换需要CPU开销才能完成。4.2什么是协程英文Coroutines是一种比线程更轻量级的存在。正如一个进程可以有多个线程一样,一个线程也可以有多个协程。最重要的是,协程不由操作系统内核管理,而完全由程序控制(即在用户态执行)。这样做的好处是性能有了很大的提升,不会像线程切换那样消耗资源。协程示意图在Python语言中有一个生成器的概念。里面有个关键字yield。当程序执行到yield关键字时,它将在该行暂停。当主线程调用send方法发送数据时,协程会接收数据继续执行。然而,yield使程序挂起,这与线程阻塞有本质区别。通过yield关键字的暂停完全由程序控制,线程的阻塞状态由操作系统内核切换。可以在Python脚本中编写如下代码并执行来体验:defconsume():whileTrue:#consumewaitingtoreceivedatanumber=yieldprint("我要执行了...开始计数:",number)consumer=consume()next(consumer)fornuminrange(0,100):print("开始执行:",num)consumer.send(num)协程Python代码NFV关键技术:X86架构基础(上)【本文为专栏作者《移动实验室》原创稿件,转载请联系原作者】点此查看该作者更多好文