虚拟化技术发展编年史
8月12日 楚倾云投稿 我已经想不起来是从什么时候开始的,突然就对计算机历史产生了浓厚的兴趣。于是我想着,要不以后所有系列文章的开篇都先和大家聊聊历史吧。
其实说来挺有意思,看过去到底是为了看未来,因为历史总是惊人的相似,几乎所有的问题都能够在历史长河中寻得答案。可惜的是,但凡历史,最是难写,笔者碍于能力有限,还望大家多指点一二。
作者:范桂飓
责编:屠敏
来源:公众号:CSDN(ID:CSDNnews)
一、什么是虚拟化?
在计算机科学中,虚拟化技术(Virtualization)是一种资源管理(优化)技术,将计算机的各种物理资源(e。g。CPU、内存以及磁盘空间、网络适配器等IO设备)予以抽象、转换,然后呈现出来的一个可供分割并任意组合为一个或多个(虚拟)计算机的配置环境。
虚拟化技术打破了计算机内部实体结构间不可切割的障碍,使用户能够以比原本更好的配置方式来应用这些计算机硬件资源。而这些资源的虚拟形式将不受现有架设方式,地域或物理配置所限制。
虚拟化技术是一个广义的术语,根据不同的对象类型可以细分为:
平台虚拟化(PlatformVirtualization):针对计算机和操作系统的虚拟化。
资源虚拟化(ResourceVirtualization):针对特定的系统资源的虚拟化,如内存、存储、网络资源等。
应用程序虚拟化(ApplicationVirtualization):包括仿真、模拟、解释技术等,如Java虚拟机(JVM)。
这里我们主要讨论的是平台虚拟化。首先提出第一个问题:当我们讨论平台虚拟化技术,实际在讨论什么?我认为讨论的是Hypervisor或称为VMM(VirtualMachineMonitor),本篇我们主要回顾VMM的发展历程,并思考之中的原因。
二、虚拟化技术发展编年史
1。开篇
1959年6月,牛津大学的计算机教授,克里斯托弗(ChristopherStrachey)在国际信息处理大会(InternationalConferenceonInformationProcessing)上发表了一篇名为《大型高速计算机中的时间共享》(TimeSharinginLargeFastComputer)的学术报告,他在文中首次提出了“虚拟化”的基本概念,还论述了什么是虚拟化技术。这篇文章被认为是最早的虚拟化技术论述,从此拉开了虚拟化发展的帷幕。
克里斯托弗还同时提出了MultiProcessing(多道程序)这一超前的概念,MultiProcessing解决了应用程序因等待外部设备而导致处理器空转问题,同时也解决了用户如何调试(Debug)代码的问题。即便在现在看来,多道程序的理念仍是操作系统在“并发”领域中的隗宝。
WhenIwrotethepaperin1959I,incommonwitheveryoneelse,hadnoideaofthedifficultieswhichwouldariseinwritingthesoftwaretocontroleitherthetimesharingormultiprogramming。IfIhadIshouldnothavebeensoenthusiasticaboutthem。
ChristopherStrachey
ChristopherStrachey
2。大型机和小型机的虚拟化
1960年,为了应对物理学领域的计算需求,美国启动Atlas超级计算机(SuperComputer)项目。同期的英国全国只有16台计算机,日不落帝国的诅咒在计算机领域也无法幸免。
1961年,由麻省理工学院的FernandoCorbato教授带领团队开始研发CTSS(CompatibleTimeSharingSystem,兼容性分时系统)项目,并由IBM提供硬件设备和工程师进行支持。分时系统可以说是硬件虚拟化的根本,CTSS为后来IBM的TSS打下了基础。
1962年,第一台Atlas超级计算机Atlas1诞生,Atlas1是第一台实现了虚拟内存(VirtualMemory)概念的计算机,并将其称为一级存储(onelevelstore)。Atlas1还是第一个实现了名为Supervisor的底层资源管理组件的计算机,Supervisor可以通过特殊的指令或代码来管理物理主机的硬件资源,例如:中央处理器的时间分配。
没错,操作系统最早的称谓其实是Supervisor,往后还被叫过一段时间的MasterControlProgram(主控程序),但最终OperatingSystem胜出了。此时你或许能够理解为什么虚拟机管理程序会被统称为Hypervisor(Super、Hyper是同意词,意为超级,但词义上Hyper比Super还要高级一些)。
1963年使用打孔机的第一代Atlas超级计算机
1960中期,IBM在ThomasJ。WatsonResearchCenter(NY)进行M4444X计算机研究项目。M4444X项目基于IBM7044(M44)实现了多个具有突破性的虚拟化概念,包括部分硬件共享(partialhardwaresharing)、时间共享(timesharing)、内存分页(memorypaging)以及实现了虚拟内存管理的VMM。
通过这些虚拟化技术,应用程序可以运行在这些虚拟的内存之中,实现了在同一台主机上模拟出多个7044系统(44X)。M4444X项目首次使用了VM(VirtualMachine)和VMM(VirtualMachineMonitor)一词,被认为是世界上第一个支持虚拟机的系统。
1964年:IBM推出了著名的System360。你或许有所耳闻,System360的开发过程被视为了计算机发展史上最大的一次豪赌,为了研发System360,IBM决定征召六万多名新员工,创建了五座新工厂。即便如此,当时的出货时间仍被不断顺延。
吉恩阿姆达尔是系统主架构师,当时的项目经理佛瑞德布鲁克斯(FrederickP。Brooks,Jr。)事后根据这项计划的开发经验,写出了同样著名的《人月神话:软件项目管理之道》(TheMythicalManMonth:EssaysonSoftwareEngineering)记述人类工程史上一项里程碑式的大型复杂软件系统开发经验。最终,IBMSystem360取得了巨大的商业成功。
System360不仅提供了新型的操作系统(让单一操作系统适用于整个系列的产品,这是System360系列大型机成功的关键),还实现了基于全硬件虚拟化(FullHardwareVirtualization)的虚拟机解决方案,包括:页式虚拟内存(4k分页虚拟存储系统),虚拟磁盘以及TSS分时系统。System360最多可提供14个虚拟机,每个虚拟机具有256k固定虚拟内存。
这里有必要着重介绍一下TSS(TimeSharingSystem,分时共享系统),它能够让一台主机上连接多个带有显示器和键盘的终端,同时允许多个用户通过主机的终端,以交互方式使用计算机,共享主机中的资源。分时操作系统本质是一个多用户交互式操作系统。
其中,“分时”的含义是将CPU占用切分为多个极短(e。g。1100sec)的时间片,每个时间片都执行着不同的任务。通过对这些时间片的轮询,就可以将一个CPU“伪装”(虚拟化)成多个vCPU,并且让每颗vCPU看起来都是并行运行的。最终达到多个用户分享使用同一台计算机,多个程序分时共享硬件和软件资源的效果,TSS被认为是最原始的虚拟化技术。
可见,最初虚拟化技术的应用和发展源于大型机对分时系统的需求。这种通过硬件的方式来生成多个可以运行独立操作系统软件的虚拟机实例,解决了早期大型计算机只能单任务处理而不能分时多任务处理的问题。
由于这种虚拟化技术是基于硬件设备来实现的,故被称为硬件虚拟化(Hardwarevirtualization)。但需要注意的是,这一说法在后来被进一步细分为了狭义的硬件虚拟化技术,现今更加为人多熟知的硬件虚拟化是指:一种对计算机或操作系统的虚拟化,能够对用户隐藏真实的计算机硬件,表现出另一个抽象的计算平台。
System360
TheMythicalManMonth:EssaysonSoftwareEngineering
3。伟大源自于伟大!
1974年,GeraldJ。Popek(杰拉尔德J波佩克)和RobertP。Goldberg(罗伯特P戈德堡)在合作论文《可虚拟第三代架构的规范化条件》(FormalRequirementsforVirtualizableThirdGenerationArchitectures)中提出了一组称为虚拟化准则的充分条件,又称波佩克与戈德堡虚拟化需求(PopekandGoldbergvirtualizationrequirements)即:虚拟化系统结构的三个基本条件。
满足这些条件的控制程序才可以被称为虚拟机监控器(VirtualMachineMonitor,简称VMM):
资源控制(ResourceControl)。控制程序必须能够管理所有的系统资源。
等价性(Equivalence)。在控制程序管理下运行的程序(包括操作系统),除时序和资源可用性之外的行为应该与没有控制程序时的完全一致,且预先编写的特权指令可以自由地执行。
效率性(Efficiency)。绝大多数的客户机指令应该由主机硬件直接执行而无需控制程序的参与。
该论文尽管基于简化的假设,但上述条件仍为评判一个计算机体系结构是否能够有效支持虚拟化提供了一个便利方法,也为设计可虚拟化计算机架构给出了指导原则。同时,GeraldJ。Popek和RobertP。Goldberg还在论文中介绍了两种Hypervisor类型,分别是类型I和类型II。
类型II(寄居或托管Hypervisor):VMM运行在传统的操作系统上,就像其他计算机程序那样运行。
特点:
VMM作为应用程序运行在主操作系统环境内;
运行效率一般较类型I低。
实现案例:
VMware5。5以前版本;
Xen3。0以前版本;
VirtualPC2004。
类型I(原生或裸机Hypervisor):这些虚拟机管理程序直接运行在宿主机的硬件上来控制硬件和管理客户机操作系统。
特点:
需要硬件支持;
VMM作为主操作系统;
运行效率高。
实现案例:
VMware5。5及以后版本;
Xen3。0及以后版本;
VirtualPC2005;
KVM。
ps:这里我特意将类型I和II的顺序调转,至于为什么,从实现案例可以看出类型I已然是时代的选择。再一个,老实说我确实为这个事实感到震惊,平台虚拟化的雏形竟然在1974年就已经确立了的这个事实。
1979年,Unix的第7个版本引入了chroot机制,意味着第一个操作系统虚拟化(OSlevelvirtualization)诞生了。chroot是直到现在我们依然在使用的一个系统调用,这个系统调用会让一个进程把指定的目录作为根目录,它的所有文件系统操作都只能在这个指定目录中进行,本质是一种文件系统层的隔离。
ps:操作系统虚拟化这个说法你或许会感到陌生,但容器(Container)你应该非常熟悉了。
在上世纪6080年代,因为虚拟化技术使得大型机和小型机获得了空前的成功。并且在相当长的一段时间里,虚拟化技术只在大型机和小型机上得到了应用,而在x86平台上的应用仍然进展缓慢。不过也可以理解,以当时x86平台的处理能力,应付一两个应用程序已然捉襟见肘,还怎么能够将资源分给更多的虚拟应用呢?
而后随着x86的流行,大型机和小型机在新兴的服务器市场中也逐渐失去了竞争力。
4。x86架构的虚拟化
直到上世纪8090年代,Intel公司(戈登摩尔)提出了摩尔定律,Windows、Mac等PC(PersonalComputer)电脑被广泛使用,Wintel联盟势如破竹,还出现了神一般的Linux服务器操作系统。
种种原因,到底是x86赢得了时代的青睐,成为了服务器的行业标准。或许在那时Intel就已经开始思考为何“生态”这件事情了。
摩尔定律的传统定义是:半导体芯片上的晶体管密度,平均每1824个月翻一番。
Wintel联盟:即微软与英特尔的合作,自20世纪80年代以来,Wintel联盟就主导着全球PC市场。
GNULinux:开源上帝。
随着x86服务器和桌面部署的增长也为企业IT基础架构带来了新的难题:
基础架构利用率低;
基础架构成本高;
IT运维成本高;
故障切换和灾难保护不足;
最终用户桌面的维护成本高昂。
而解决这些难题就是新时代赋予虚拟化技术的历史任务,整个8090年代,虚拟化技术及公司如同雨后春笋般涌现。
1987年:InsigniaSolutions公司演示了一个称为SoftPC的软件模拟器,这个模拟器允许用户在UnixWorkstations上运行DOS应用。当时一个可以运行MicrosoftDOS的PC需要1,500美金,而使用SoftPC模拟,就可以直接在大型工作站上运行MicrosoftDOS了。
1989年,InsigniaSolutions发布了Mac版的SoftPC,使苹果用户不仅能运行DOS,还能运行Windows操作系统。
1990年,KeirFraser和IanPratt创建了XenServer的初始代码工程(项目)。
1997年,苹果开发了VirtualPC,后来又卖给了Connectix公司。
1998年,著名的x86仿真模拟器Bochs发布。
1999年,VMware公司率先推出针对x86平台推出了可以流畅运行的商业虚拟化软件VMawareWorkstation。
2000年,FreeBSDjail,真正意义上的第一个功能完整的操作系统虚拟化技术。利用这个技术,FreeBSD的系统管理者,可以创造出几个小型的软件系统,这些软件系统被称为jails(监狱,即容器。ps:不禁感慨,取名真的很重要)。
2001年,VMWare发布ESX和GSX,是ESXi的前身。同年,FabriceBellard也发布了目前最流行的,采用了动态二进制翻译(BinaryTranslation)技术的开源虚拟化软件QEMU(QuickEMUlator)的第一个版本。
5。基于二进制翻译的全虚拟化
此时,虚拟化技术的共同目标就是将x86架构转变为通用的共享硬件基础架构,使应用程序运行环境在隔离性、移动性和操作系统类型方面都有选择的空间。首先了解一下x86架构的特点。
CPU为了保证程序代码执行的安全性,多用户的独立性以及保证操作系统的稳定性,提出了CPU执行状态的概念。它有效的限制了不同程序之间的数据访问能力,避免了非法的内存数据操作,同时也避免了应用程序错误操作计算机的物理设备。
一般的,CPU都会划分为用户态和内核态,而x86CPU更是细分为了Ring03四种执行状态。
Ring0核心态(KernelMode):是操作系统内核的执行状态(运行模式),运行在核心态的代码可以无限制的对系统内存、设备驱动程序、网卡接口、显卡接口等外部设备进行访问。
显然,只有操作系统能够无限制的访问内存、磁盘、鼠键等外围硬件设备的数据,因为操作系统就是作为计算机硬件资源管理器而存在的,操作系统就是为了让多个普通应用程序可以更简单、安全的运行在同一台计算机上而存在的“特殊的应用程序”。
Ring3用户态(UserMode):运行在用户态的程序代码需要受到CPU的检查,用户态程序代码只能访问内存页表项中规定能被用户态程序代码访问的页面虚拟地址(受限的内存访问),而且还只能访问IOPermissionBitmap中规定的能被用户态程序代码访问的端口,不能直接访问外围硬件设备、不能抢占CPU。
也很显然,所有的应用程序都应该运行在用户态中。当应用程序需要访问外围硬件设备时,CPU会通过特别的接口去调用核心态的代码,以这种旁路的方式来应用程序对硬件设备的调用。如果用户态的应用程序直接调用硬件设备的话,就会被操作系统捕捉到并触发异常,弹出警告窗口。
可见,x86架构与大型机不同,当时的x86体系结构缺乏必要的针对虚拟化的硬件支持,难以直接满足波佩克与戈德堡的虚拟化需求,所以x86架构天然不是一个可虚拟化的架构。
x86架构的CPU中有17条指令成为了虚拟化最大的障碍,错误执行这些指令会导致操作系统显示警告、终止应用程序甚至完全崩溃。当时VMware提出了解决这个问题的思路:在虚拟机生成这些特殊的指令时将它们“困住”,然后将它们转换成可虚拟化的安全指令,同时保证其他所有的指令不受到干扰地执行。这样就产生了一种与主机硬件匹配并保持软件完全兼容性的高性能虚拟机。
这就是全虚拟化(Fullvirtualization)技术诞生的背景必须使用纯软件实现的方式构造VMM。VMware首创了这项技术,一举稳坐虚拟化龙头老大。
全虚拟化是指虚拟机模拟了完整的底层硬件,包括处理器、物理内存、时钟、外设等,使得为原始硬件设计的操作系统或其它系统软件完全不做任何修改就可以在虚拟机中运行。客户机操作系统(GuestOS)与真实硬件之间的交互,可以看成是通过一个预先规定的硬件接口进行的。全虚拟化VMM以完整模拟硬件的方式提供全部接口(同时还必须模拟特权指令的执行过程)。
全虚拟化的工作原理:虚拟机是对真实计算环境的抽象和模拟,VMM需要为每个虚拟机分配一套数据结构来管理它们状态,包括vCPU的全套寄存器,物理内存的使用情况,虚拟设备的状态等等。
VMM调度虚拟机时,会将其部分状态恢复到HostOS中。但并非所有的状态都需要恢复,例如主机CR3寄存器中存放的是VMM设置的页表物理地址,而不是GuestOS设置的值。
pCPU直接运行GuestOS的机器指令时,由于GuestOS运行在低特权级别(Ring1),如果GuestOS直接访问HostOS的特权状态(如写GDT寄存器),就会因为权限不足导致pCPU产生异常,然后将运行权主动交还给VMM。
此外,外部中断的到来也会影响VMM的运行。VMM可能需要先将该虚拟机的当前状态写回到状态数据结构中,分析虚拟机被挂起的原因,然后代表GuestOS执行相应的特权操作。最简单的情况,如GuestOS对CR3寄存器的修改,只需要更新虚拟机的状态数据结构即可。
一般而言,大部分情况下,VMM需要经过复杂的流程才能完成原本简单的操作。最后VMM将运行权还给GuestOS,GuestOS从上次被中断的地方继续执行,或处理VMM“塞”入的虚拟中断和异常。
这种经典的虚拟机运行方式被称为TrapAndEmulate(捕获模拟),虚拟机对于GuestOS完全透明,GuestOS不需要任何修改,但是VMM的设计会比较复杂,系统整体性能受到明显的损害。
举例来说:x86平台中,操作系统执行切换进程页表的操作,真实硬件会通过提供一个特权CR3寄存器来实现该接口,操作系统只需执行movpgtable,cr3汇编指令即可。而全虚拟化VMM就必须要完整地模拟该接口执行的全过程。
如果硬件(主要是CPU)不提供虚拟化的特殊支持的话,那么这个模拟过程将会十分复杂:一般而言,VMM必须运行在最高优先级来完全控制宿主机操作系统(HostOS),而GuestOS需要降级运行,从而不能执行特权操作。
当GuestOS执行前面的特权汇编指令时,HostOS产生异常(GeneralProtectionException),执行控制权重新从GuestOS转到VMM手中。VMM事先分配一个变量作为影子CR3寄存器给GuestOS,将pgtable(页表)代表的GuestOS物理地址(GuestPhysicalAddress)填入影子CR3寄存器,然后VMM还需要pgtable翻译成主机物理地址(HostPhysicalAddress)并填入物理CR3寄存器,最后返回到GuestOS中。随后VMM还将处理复杂的GuestOS缺页异常(PageFault)。
简单来说,就是全虚拟化需要在VMM中模拟出一颗包含了控制单元、运算单元、存储单元、IS(指令集)的CPU。此外,还需要模拟一张进行虚拟存储地址和物理存储地址转换的页表。此外,还需要在VMM模拟磁盘设备控制器、网络适配器等等各种IO外设接口。
如此依赖,GuestOS就不知道自己其实是个虚拟机了呀,它收到了欺骗。可以想象得到,全虚拟化这种处理器密集型的虚拟化技术实现是异常困难且低效的。
比较著名的全虚拟化VMM有MicrosoftVirtualPC、VMwareWorkstation、SunVirtualBox、ParallelsDesktopforMac和QEMU。QEMU在今年(2019)对外宣称可以模拟所有设备。天啊,这简直是个奇迹般的伟大软件。
但基于这样的前提,全虚拟化VMM必须要克服许多难以解决的问题,例如:
(1)确保VMM控制所有的系统资源
x86处理器有4个特权级别,Ring0Ring3,只有运行在Ring02时,处理器才可以访问特权资源或执行特权指令;运行在Ring0级时,处理器可以访问所有的特权状态。x86平台上的操作系统一般只使用Ring0和Ring3这两个级别,操作系统运行在Ring0级,用户进程运行在Ring3级。
为了满足资源控制(ResourceControl)虚拟化需求条件,VMM就必须运行在Ring0级,同时为了避免GuestOS控制系统资源,GuestOS不得不降低自身的运行级别,运行在Ring1或Ring3级(Ring2不使用)。
(2)特权级压缩(RingCompression):VMM使用分页或段限制的方式来保护物理内存的访问,但是64位模式下段限制不起作用,而分页又不区分Ring0,1,2。
为了统一和简化VMM的设计,GuestOS只能和Guest进程一样运行在Ring3级。VMM必须监视GuestOS对GDT、IDT等特权资源的设置,防止GuestOS运行在Ring0级,同时又要保护降级后的GuestOS不受Guest进程的主动攻击或无意破坏。
(3)特权级别名(RingAlias):特权级别名是指GuestOS在虚拟机中运行的级别并不是它所期望的。VMM必须保证GuestOS不能获知正在虚拟机中运行这一事实,否则可能打破等价性(Equivalence)虚拟化需求条件。
例如:x86处理器的特权级别存放在CS代码段寄存器内,GuestOS可以使用非特权push指令将CS寄存器压栈,然后pop出来检查该值。又如:GuestOS在低特权级别时读取特权寄存器GDT、LDT、IDT和TR,并不发生异常,从而可能发现这些值与自己期望的不一样。
为了解决这个挑战,VMM可以使用动态二进制翻译(BinaryTranslation)的技术,例如预先把pushcs指令替换,在栈上存放一个影子CS寄存器值;又如:可以把读取GDT寄存器的操作sgdtdest改为movlfakegdt,dest。
(4)地址空间压缩(AddressSpaceCompression)
地址空间压缩是指VMM必须在GuestOS的地址空间中保留一部分供其使用。例如:中断描述表寄存器(IDTRegister)中存放的是中断描述表的线性地址,如果GuestOS运行过程中来了外部中断或触发处理器异常,必须保证运行权马上转移到VMM中,因此VMM需要将GuestOS的一部分线性地址空间映射成自己的中断描述表的主机物理地址。
VMM可以完全运行在GuestOS的地址空间中,也可以拥有独立的地址空间,后者的话,VMM只占用GuestOS很少的地址空间,用于存放中断描述表和全局描述符表(GDT)等重要的特权状态。无论如何哪种情况,VMM应该防止GuestOS直接读取和修改这部分地址空间。
(5)处理GuestOS的缺页异常
内存是一种非常重要的系统资源,VMM必须全权管理,GuestOS理解的物理地址只是客户机物理地址(GuestPhysicalAddress),并不是最终的主机物理地址(HostPhysicalAddress)。
当GuestOS发生缺页异常时,VMM需要知道缺页异常的原因,是Guest进程试图访问没有权限的地址,或是客户机线性地址(GuestLinearAddress)尚未翻译成客户机物理地址,还是客户机物理地址尚未翻译成主机物理地址。
一种可行的解决方法是VMM为GuestOS的每个进程的页表构造一个影子页表(ShadowPageTable),维护GuestLinearAddress到HostPhysicalAddress的映射,主机CR3寄存器存放这个影子页表的物理内存地址。
VMM同时维护一个GuestOS全局的GuestPhysicalAddress到HostPhysicalAddress的映射表。发生缺页异常的地址总是GuestLinearAddress,VMM先去GuestOS中的页表检查原因,如果页表项已经建立,即对应的GuestPhysicalAddress存在,说明尚未建立到HostPhysicalAddress的映射,那么VMM分配一页物理内存,将影子页表和映射表更新;否则,VMM返回到GuestOS,由GuestOS自己处理该异常。
(6)处理GuestOS中的系统调用(SystemCall)
系统调用是操作系统提供给用户的服务例程,使用非常频繁。最新的操作系统一般使用SYSENTERSYSEXIT指令对来实现快速系统调用。SYSENTER指令通过IA32SYSENTERCS,IA32SYSENTEREIP和IA32SYSENTERESP这3个MSR(ModelSpecificRegister)寄存器直接转到Ring0级;而SYSEXIT指令不在Ring0级执行的话将触发异常。
因此,如果VMM只能采取TrapAndEmulate的方式处理这2条指令的话,整体性能将会受到极大损害。
(7)转发虚拟的中断和异常
所有的外部中断和pCPU的异常直接由VMM接管,VMM构造必需的虚拟中断和异常,然后转发给GuestOS。VMM需要模拟硬件和操作系统对中断和异常的完整处理流程,例如VMM先要在GuestOS当前的内核栈上压入一些信息,然后找到GuestOS相应处理例程的地址,并跳转过去。
VMM必须对不同的GuestOS的内部工作流程比较清楚,这增加了VMM的实现难度。同时,GuestOS可能频繁地屏蔽中断和启用中断,这两个操作访问特权寄存器EFLAGS,必须由VMM模拟完成,性能因此会受到损害。GuestOS重新启用中断时,VMM需要及时地获知这一情况,并将积累的虚拟中断转发。
(8)GuestOS频繁访问特权资源:GuestOS对特权资源的每次访问都会触发CPU异常,然后由VMM模拟执行,如果访问过于频繁,则系统整体性能将会受到极大损害。比如对中断的屏蔽和启用,cli(ClearInterrupts)指令在Pentium4处理器上需要花费60个时钟周期(cycle)。
又比如:处理器本地高级可编程中断处理器(LocalAPIC)上有一个操作系统可修改的任务优先级寄存器(TaskPriorityRegister),IOAPIC将外部中断转发到TPR值最低的处理器上(期望该处理器正在执行低优先级的线程),从而优化中断的处理。TPR是一个特权寄存器,某些操作系统会频繁设置(LinuxKernel只在初始化阶段为每个处理器的TPR设置相同的值)。
显然,基于TrapAndEmulate处理方式的全虚拟化虽能够以纯软件的方式完成虚拟化并解决了许多问题,但同时也带来了极大的设计复杂性和性能下降。而对于这两个问题,半虚拟化(Partialvirtualization)想到了一个好办法:改造GuestOS,将GuestOS原来所有需要被VMM截获、模拟的指令和操作全部改造成与VMM协同工作的指令(hypercall)和操作。
VMM不再隐瞒了,因为你(GuestOS)已经知道自己就是个虚拟机了。其核心思想是:动态或静态地改变GuestOS对特权状态访问的操作,尽量减少产生不必要的硬件异常,同时简化VMM的设计。
6。半虚拟化
半虚拟化是一种通过修改GuestOS部分访问特权状态的代码以便直接与VMM交互的技术。在半虚拟化虚拟机中,部分硬件接口以软件的形式提供给GuestOS,这可以通过Hypercall(VMM提供给GuestOS的直接调用,与系统调用类似)的方式来提供。
例如:GuestOS把切换页表的代码修改为调用Hypercall来直接完成修改影子CR3寄存器和翻译地址的工作。由于不需要产生额外的异常和模拟部分硬件执行流程,半虚拟化可以大幅度提高性能,比较著名的VMM有Denali、Xen。
2003年,英国剑桥大学的一位讲师发布了开源虚拟化项目Xen,并成立XenSource公司,通过半虚拟化技术为x8664提供虚拟化支持。同年,Intel正式公布将在x86平台的CPU上支持虚拟化技术VT。同年VMWare也被EMC收购,成为EMC迄今最成功的一笔收购。同年,微软收购Connectix公司获得VirtualPC虚拟化技术。
相较于全虚拟化,半虚拟化VMM只需要模拟部分底层硬件,因此GuestOS不做修改是无法在虚拟机中运行的,甚至运行在虚拟机中的其它程序也需要进行修改,如此代价,换来的就是接近于物理机的虚拟机性能。
有意思的是,半虚拟化其实也很尴尬,对于Linux而言自然是改了就改了,但Windows你要怎么改?人家可是闭源的。写到这里,不禁会想起自己写过的代码,拆东墙补西墙可不值得提倡,要从根源上解决问题。而这个根源自然就是CPU。
既然全虚拟化性能低的主要原因是花费了太多的精力去捕获CPU异常并模拟CPU行为,那么如果CPU本身就为VMM提供了便利,那岂不是从根本上解决了这个问题?这就是硬件辅助虚拟化(Hardwareassistedvirtualization)。
7。基于硬件辅助的全虚拟化
IntelVT(IntelVirtualizationTechnology)和AMDV是目前x86平台上可用的两种硬件辅助虚拟化技术。VTx为IA32处理器增加了两种操作模式:VMXrootoperation和VMXnonrootoperation。
VMM自己运行在VMXrootoperation模式,VMXnonrootoperation模式则由GuestOS使用。两种操作模式都支持Ring03这4个特权级,因此VMM和GuestOS都可以自由选择它们所期望的运行级别,这两种操作模式可以互相转换。
运行在VMXrootoperation模式下的VMM通过显式调用VMLAUNCH或VMRESUME指令切换到VMXnonrootoperation模式,硬件自动加载GuestOS的上下文,于是GuestOS获得运行,这种转换称为VMentry。
GuestOS运行过程中遇到需要VMM处理的事件,例如外部中断或缺页异常,或者主动调用VMCALL指令调用VMM的服务的时候(与系统调用类似),硬件自动挂起GuestOS,切换到VMXrootoperation模式,恢复VMM的运行,这种转换称为VMexit。
VMXrootoperation模式下软件的行为与在没有VTx技术的处理器上的行为基本一致;而VMXnonrootoperation模式则有很大不同,最主要的区别是此时运行某些指令或遇到某些事件时,发生VMexit。
例如:在上面的例子中,GuestOS能够执行修改页表的汇编指令,再无需VMM进行捕获、模拟。从而减少了相关的性能开销,也极大简化了VMM设计,进而使VMM能够按通用标准进行编写,性能更加强大。
又因为VMM和GuestOS共享底层的处理器资源,所以硬件需要一个物理内存区域来自动保存或恢复彼此执行的上下文。这个区域称为虚拟机控制块(VMCS),包括客户机状态区(GuestStateArea),主机状态区(HostStateArea)和执行控制区。
VMentry时,硬件自动从客户机状态区加载GuestOS的上下文。并不需要保存VMM的上下文,原因与中断处理程序类似,因为VMM如果开始运行,就不会受到GuestOS的干扰,只有VMM将工作彻底处理完毕才可能自行切换到GuestOS。
而VMM的下次运行必然是处理一个新的事件,因此每次VMMentry时,VMM都从一个通用事件处理函数开始执行;VMexit时,硬件自动将GuestOS的上下文保存在客户机状态区,从主机状态区中加载VMM的通用事件处理函数的地址,VMM开始执行。而执行控制区存放的则是可以操控VMentry和exit的标志位,例如标记哪些事件可以导致VMexit,VMentry时准备自动给GuestOS“塞”入哪种中断等等。
客户机状态区和主机状态区都应该包含部分物理寄存器的信息,例如控制寄存器CR0,CR3,CR4;ESP和EIP(如果处理器支持64位扩展,则为RSP,RIP);CS,SS,DS,ES,FS,GS等段寄存器及其描述项;TR,GDTR,IDTR寄存器;IA32SYSENTERCS,IA32SYSENTERESP,IA32SYSENTEREIP和IA32PERFGLOBALCTRL等MSR寄存器。
客户机状态区并不包括通用寄存器的内容,VMM自行决定是否在VMexit的时候保存它们,从而提高了系统性能。客户机状态区还包括非物理寄存器的内容,比如一个32位的ActiveState值表明GuestOS执行时处理器所处的活跃状态,如果正常执行指令就是处于Active状态,如果触发了三重故障(TripleFault)或其它严重错误就处于Shutdown状态,等等。
执行控制区用于存放可以操控VMentry和VMexit的标志位,包括:
Externalinterruptexiting:用于设置是否外部中断可以触发VMexit,而不论GuestOS是否屏蔽了中断。
Interruptwindowexiting:如果设置,当GuestOS解除中断屏蔽时,触发VMexit。
UseTPRshadow:通过CR8访问TaskPriorityRegister(TPR)的时候,使用VMCS中的影子TPR,可以避免触发VMexit。同时执行控制区还有一个TPR阈值的设置,只有当GuestOS设置的TR值小于该阈值时,才触发VMexit。
CRmasksandshadows:每个控制寄存器的每一位都有对应的掩码,控制GuestOS是否可以直接写相应的位,或是触发VMexit。同时VMCS中包括影子控制寄存器,GuestOS读取控制寄存器时,硬件将影子控制寄存器的值返回给GuestOS。
VMCS还包括一组位图以提供更好的适应性:
Exceptionbitmap:选择哪些异常可以触发VMexit。
IObitmap:对哪些16位的IO端口的访问触发VMexit。
MSRbitmaps:与控制寄存器掩码相似,每个MSR寄存器都有一组“读”的位图掩码和一组“写”的位图掩码。
每次发生VMexit时,硬件自动在VMCS中存入丰富的信息,方便VMM甄别事件的种类和原因。VMentry时,VMM可以方便地为GuestOS注入事件(中断和异常),因为VMCS中存有GuestOS的中断描述表(IDT)的地址,因此硬件能够自动地调用GuestOS的处理程序。
传统的全虚拟化实现在有了硬件的辅助之后,由于CPU引入了新的操作模式,VMM和GuestOS的执行由硬件自动隔离开来,任何关键的事件都可以将系统控制权自动转移到VMM,因此VMM能够完全控制系统的全部资源。GuestOS也可以运行在它所期望的最高特权级别,因此特权级压缩和特权级别名的问题迎刃而解,而且GuestOS中的系统调用也不会触发VMexit。
硬件使用物理地址访问虚拟机控制块(VMCS),而VMCS保存了VMM和GuestOS各自的IDTR和CR3寄存器。因此VMM可以拥有独立的地址空间,GuestOS能够完全控制自己的地址空间,地址空间压缩的问题也不存在了。中断和异常虚拟化的问题也得到了很好的解决。
VMM只用简单地设置需要转发的虚拟中断或异常,在VMentry时,硬件自动调用GuestOS的中断和异常处理程序,大大简化VMM的设计。同时,GuestOS对中断的屏蔽及解除可以不触发VMexit,从而提高了性能。而且VMM还可以设置当GuestOS解除中断屏蔽时触发VMexit,因此能够及时地转发积累的虚拟中断和异常。
另外,纯软件实现的VMM目前缺少对64位客户操作系统的支持,而CPU的虚拟化技术除支持广泛的传统操作系统类型之外,还支持64位客户操作系统。硬件辅助虚拟技术提高了虚拟机的性能以及兼容性。
需要注意的是,上文中我们提到了全虚拟化、半虚拟化和硬件辅助的全虚拟化,但这种分类实际上并不绝对,一个优秀的VMM往往融合了多项技术。
例如:VMwareWorkstation是一个著名的全虚拟化的VMM,但是它使用了一种被称为动态二进制翻译(BinaryTranslation)的技术把对特权状态的访问转换成对影子状态的操作,从而避免了低效的TrapAndEmulate的处理方式,这与半虚拟化相似,只不过半虚拟化是静态地修改程序代码。
看得出硬件辅助虚拟化技术必然是未来的方向,IntelVT的处理器级虚拟化技术还需要进行以下优化:
(1)提高操作模式间的转换速度
两种操作模式间的转换发生之如此频繁,如果不能有效减少其转换速度,即使充分利用硬件特性,虚拟机的整体性能也会大打折扣。早期的支持硬件辅助虚拟化技术的Pentium4处理器需要花费2409个时钟周期处理VMentry,花费508个时钟周期处理由缺页异常触发的VMexit,代价相当高。
随着Intel技术的不断完善,在新的Core架构上,相应时间已经减少到937和446个时钟周期。未来硬件厂商还需要进一步提高模式的转换速度,并提供更多的硬件特性来减少不必要的转换。
(2)优化翻译后援缓冲器(TLB)的性能
每次VMentry和VMexit发生时,由于需要重新加载CR3寄存器,因此TLB(TranslationLookasideBuffer)被完全清空。虚拟化系统中操作模式的转换发生频率相当高,因此系统的整体性能受到明显损害。一种可行的方案是为VMM和每个虚拟机分配一个全局唯一ID,TLB的每一项附加该ID信息来索引线性地址的翻译。
(3)提供内存管理单元(MMU)虚拟化的硬件支持
即使使用IntelVT技术,VMM还是得用老办法来处理GuestOS中发生的缺页异常以及GuestOS的客户机物理地址到主机物理地址的翻译,本质原因是VMM完全控制主机物理内存,因此GuestOS中的线性地址的翻译同时牵涉到VMM和GuestOS的地址空间,而硬件只能看到其中的一个。
Intel和AMD提出了各自的解决方案,分别叫做EPT(ExtendedPageTable)和NestedPaging。这两种技术的基本思想是,无论何时遇到客户机物理地址,硬件自动搜索VMM提供的关于该GuestOS的一个页表,翻译成主机物理地址,或产生缺页异常来触发VMexit。
(4)支持高效的IO虚拟化
IO虚拟化需要考虑性能、可用性、可扩展性、可靠性和成本等多种因素。最简单的方式是VMM为虚拟机模拟一个常见的IO设备,该设备的功能由VMM用软件或复用主机IO设备的方法实现。
例如:VirtualPC虚拟机提供的是一种比较古老的S3Trio64显卡。这种方式提高了兼容性,并充分利用GuestOS自带的设备驱动程序,但是虚拟的IO设备功能有限且性能低下。为了提高性能,VMM可以直接将主机IO设备分配给虚拟机,这会带来两个主要挑战:
如果多个虚拟机可以复用同一个设备,VMM必须保证它们对设备的访问不会互相干扰。
如果GuestOS使用DMA的方式访问IO设备,由于GuestOS给出的地址并不是主机物理地址,VMM必须保证在启动DMA操作前将该地址正确转换。Intel和AMD分别提出了各自的解决方案,分别称为DirectIO(VTd)和IOMMU,希望用硬件的手段解决这些问题,降低VMM实现的难度。
2004年,微软发布VirtualServer2005计划,象征着虚拟化技术正式进入主流市场。
2005年,OpenVZ发布,这是Linux操作系统的容器化技术实现,同时也是LXC的核心实现。
2006年,Intel和AMD等厂商相继将对虚拟化技术的支持加入到x86体系结构的中央处理器中(AMDV,IntelVTx),使原来纯软件实现的各项功能可以用借助硬件的力量实现提速。同年,红帽将Xen作为RHEL的默认特性。同年,AmazonWebServices(AWS)开始以Web服务的形式向企业提供IT基础设施服务,现在通常称为云计算。
ps:虚拟化和云计算不解的渊源自此开始了。
2007年1月,Sun公司发布了开源虚拟化软件VirtualBox。同年Xen被Citrix(思杰)收购。
2007年2月,LinuxKernel2。6。20合入了由以色列公司Qumranet开发的虚拟化内核模块KVM(KernelbasedVirtualMachine,基于内核的虚拟机),支持KVM的前提是CPU必须要支持虚拟化技术。
2008年第一季度,微软同时发布了WindowsServer2008R2及虚拟化产品HyperV。
2008年6月,LinuxContainer(LXC)发布0。1。0版本,其可以提供轻量级的虚拟化,用来隔离进程和资源。是Docker最初使用的容器技术支撑。
2008年9月4日,RedHat收购以色列公司Qumranet,并着手使用KVM替换在RedHat中的使用的Xen。
2009年9月,红帽发布RHEL5。4,在原先的Xen虚拟化机制之上,将KVM添加了进来。同年,阿里云写下第一行代码。
2010年11月,红帽发布RHEL6。0,这个版本将默认安装的Xen虚拟化机制彻底去除,仅提供KVM虚拟化机制。
当年,Xen虽然作为一项广泛应用于Linux发行版中的虚拟化技术,但却迟迟没有集成到Linux内核中,红帽也许是出于对这种脱离内核的维护方式感到不爽,加之当时思杰和微软表现的很非常亲密,导致红帽萌生了放弃Xen的想法,并在正式采用KVM的一年后,就宣布彻底放弃Xen。硬件辅助虚拟化的到来,Xen引以为傲的半虚拟化技术也随之在主流Linux发行厂商中衰落了。
2010年10月21日,NASA发布了可以IaaS(基础设施即服务)云操作系统OpenStack,第一个版本便是众所周知Austin(奥斯丁)。OpenStack挽手自主可控的口号,推动了云计算在国内的全面爆发。
2011年初,IBM找上老搭档红帽,表示KVM这个东西值得加大力度去做。于是到了5月,IBM和红帽,联合惠普和英特尔一起,成立了开放虚拟化联盟(OpenVirtualizationAlliance),加速KVM投入市场的速度,由此避免VMware一家独大的情况出现。
联盟成立之时,红帽的发言人表示:“大家都希望除VMware之外还有一种开源选择。未来的云基础设施一定会基于开源。我们想要营造一个小厂商们可以轻松加入的生态环境。”
ps:现在回头再看,企业之所以能够长盛不衰,长远的洞察力至关重要。
8。操作系统虚拟化(容器)
2013年3月15日,在加利福尼亚州圣克拉拉召开的Python开发者大会上,DotCloud的创始人兼首席执行官SolomonHvkes在一场仅五分钟的微型演讲中,首次提出了Docker这一概念,并于会后将其源码开源并托管到Github。
最初的Docker就是使用了LXC再封装了其他的一些功能。可以看出,Docker的成功,与其说是技术的创新,还不如说是一次组合式的创新。
2014年6月,Docker发布了第一个正式版本v1。0。同年,Redhat和AWS就宣布了为Docker提供官方支持。
在传统操作系统中,所有用户的进程本质上是在同一个操作系统的实例中运行,因此内核或应用程序的缺陷可能影响到其它进程。操作系统虚拟化(OSlevelvirtualization)是一种在服务器操作系统中使用的、没有VMM层的轻量级虚拟化技术,内核通过创建多个虚拟的操作系统实例(内核和库)来隔离不同的进程(容器),不同实例中的进程完全不了解对方的存在。
操作系统虚拟化看似与上述提到过的几种硬件虚拟化方式一样,都是产生多个操作系统,但操作系统虚拟化与硬件虚拟化之间还是有很多不同之处,其中最核心的区别就是:操作系统虚拟化是操作系统的虚拟化,而硬件虚拟化是计算机的虚拟化。前者隔离操作系统资源,而后者隔离计算机硬件资源。
ps:容器技术之所以火热,是因为容器隔离性封装的特性,为运维能力引入了“可编程性”,开发人员借助容器得以SoftwareDefineOperation。
2015年7月21日:Kubernetesv1。0发布!进入云原生时代。
2018年,IBM正式收购Redhat以弥补在云计算市场的战略失败。同年,微软收购Github。开源的历史会铭记这一天。
2019年,全球最大的开源盛会KubeConCloudNativeConOpenSourceSummit、OpenInfrastructureSummit相继在上海举办。中国的开源会铭记这一天。
注:本篇文章将会一直更新下去!
四、最后
对于篇幅较长的文章,我都习惯使用三句话来进行总结:
虚拟化的发展:纵观虚拟化技术的发展历史,可以看到它始终如一的目标就是实现对IT资源的充分利用。
虚拟化与云计算:虚拟化是IT资源的抽象,云计算则是基于虚拟化实现的更上层的对企业业务能力的抽象。
云计算与开源:开源是引诱开发者的苹果,而开发者则是企业的核心资产。云的世界,得开发者,得天下。
参考文档:https:www。ibm。comdeveloperworkscnlinuxlcnvtindex。html
作者:范桂飓,九州云(99Cloud)OpenStack研发工程师,曾先后服务于WindowsAzure、RedhatOpenStack与ProphetechHyperMotion。云物互联公号主,现专注于探索云计算、边缘计算、SDN与物联网的深度结合应用场景。
投诉 评论 知识付费还是内容付费?网络时代的内容、体验与注意力今天所谓“知识付费”的核心,实际上是用户在为内容生产者对于知识的再次阐释而付费。在注意力稀缺的网络时代,出现了一种崭新的内容经济学。内容是一种“体验产品”,内容供应商必须采用各……
免费公开课60分钟教你写好产品体验报告,增加求职竞争力众所周知,写产品工作相关的文档,是每个产品经理都必须掌握的基本功,也是大部分企业招聘产品经理时的基本要求:而产品体验报告,是新人入行时相对容易掌握,且最适合作为面试作品的……
在2B和2C之间,还有一个2H驱动5G成功的商业场景到底是什么,至今还没有争出个结论个人数字化的市场空间还有多大?实体企业的数字化能否给我们带来期望中的产业增量?2H的数字化,或者说家庭互联网,会不会是一个……
虚拟化技术发展编年史我已经想不起来是从什么时候开始的,突然就对计算机历史产生了浓厚的兴趣。于是我想着,要不以后所有系列文章的开篇都先和大家聊聊历史吧。其实说来挺有意思,看过去到底是为了看未来……
盘点PRD中易遗漏的三类非正面需求PRD除了描述产品的正面需求,即要什么之外,还要描述产品的非正面需求,即我不要什么,或预防什么。笔者将非正面需求归为三类:排除项、异常项、默认项。一、需求的排除项……
4个层次,解析产品区块链通证产品笔者以4年产品经理的知识沉淀为基础,结合各位产品大佬的见解,分析了什么是产品与区块链通证产品。一个事情做上一定时间,如果没有做出足够的成绩,你会开始忍不住去想很多问题,比……
Costco成功的秘密:诚实是最好的策略“诚实是智慧之书的第一章。”杰弗逊最近,神店Costco在上海开张,场面火爆,有人说这是用购买力给老美上了一课,有人说这证明了两国人民情真意切,总之皆大欢喜。……
【天天问每周精选】第86期:直播暂停后并不会断点续播,为什么曾几何时,我看到直播有暂停按钮,想着暂停后回来接着看,结果回来发现接着播放的时间点是最新画面,并不是续播,愤懑这和刷新有什么区别,所以在天天问我们和大家讨论了直播的一些事情一起……
万字真言互联网人最新装逼手册所谓隔行如隔山,每行都有每行的专业术语、黑话,开会、对话、写方案,道行深不深、逼格高不高就看能用多少专业名词和缩写了,感觉不认识几个名词都不好意思在这行混下去。这不,最近……
Keep不懂克制,发展之路道阻且长笔者梳理了keep的发展历程,对模块功能重复、内容冗杂问题进行了分析。几年前,Keep是以克制的形象出现的。不止是鼓励用户“自律给我自由”,更重要的是,最初的Keep产品……
关于社交产品的浴室沉思即使大多数社交产品都只是像烟花一样在大众视野里转瞬即逝,但都是在创造一种可能,一种改变国内社交格局的可能。写文章的习惯,从我做产品开始就养成了,到现在差不多得写了十几篇文……
快消品行业的变革,从5个方面开始快消品行业将围绕新消费、新商品、新营销、新渠道和数字化这5个方面发生变革,企业需要理清思路,以实际的行动从这五个方面做出一个系统化的规划。种种迹象表明:快消品行业开始进入……
快手回春,但还缺一个自己的刘炽平相比字节跳动系透支式的强控制变现打法,快手一直走得是不温不火的佛系路线,不过度拔苗助长的价值观,让快手保存的社交火种,有机会培育出一个巨大的直播市场。一、7。8的内容生产……
品牌商与直播营销随着智能手机的普及,流量的可控性,直播形式渐渐的在电商平台上起了一个领头的代表作用,本文就跟大家聊聊品牌商与直播营销的这些事,enjoy今天我来跟大家讲一讲直播跟品牌之间……
反996,还得算算摸鱼时间如果你真的仔细去问每一个八小时工作制的白领,他们每天到底有多少时间放在工作上,很可能的情况是:不到8小时。996的问题这些天已经讨论太多太多了。维度各式各样,每一个维度都……
当我们在谈论瑞幸咖啡的时候,我们谈论什么?当我们在谈论瑞幸咖啡这个现象级的企业时,我们该谈论什么?是不到一年22亿美元的估值,9个月烧钱超8亿,还是与星巴克差异化的行业模式设计,高效的新零售实践以及品牌塑造方法论?……
百度腾讯的产互之战,“小程序”或许是胜负手?人们总是高估未来一到两年的变化,但却低估未来10年的变革。短短一年多的时间,toB变成了中国互联网的显学。3月末,马化腾在IT领袖峰会上谈及5G和AI驱动产业互联网……
短视频行业美梦破灭:谁都想成下一个抖音、快手距离第一波短视频爆发已过去近4年,抖音也有2。5岁。如今,抖音、快手构筑的短视频“美梦”究竟如何了呢?各种“南抖音,北快手”的学徒们活的还好吗?2015年是短视频元年,小……
4个观点,告诉你如何做好教师管理工作笔者为我们介绍了做好教师管理工作是多么重要,好的教师管理工作可以为学生、为机构提供良性贡献。接下来,让我们来看看笔者是怎么说的吧:在教育机构发展期,如何做好教师队伍的管理……
从蓝海到红海,社交内容电商路在何方?万变不离其宗,产品质量、用户体验永远是重中之重。跟着网红、明星们买买买,已经成为很多人习以为常的购物模式,小红书、蘑菇街等社交电商也一时间成为网购的新宠。剁手新姿势……
抖快进一步搭建电商功能,非标品或将成为短视频新发力点?种种迹象表明,今年电商将会完成较大跨度的成长,甚至成为一些内容机构的核心商业模式,对平台、创作者、品牌主、广告营销产生较大影响,在内容行业有着更多分量。短视频平台在搭建电……
建设全渠道协同服务平台保险新渠道(二)要想构建全渠道协同服务平台,企业必须要先“认识”用户或者标的物,通过对用户分层、分群进行有限资源的配备,从而实现降本增效的目的。销售很多时候就是做渠道,吃透“渠道”也就有……
微博“仅半年可见”为了谁?微博用户,真的需要仅半年可见这个功能吗?4月4日晚间,微博管理员发消息称,为了增强用户对自己账号内容的自主性和处理能力,微博方面新增了“仅半年内微博可见”的功能。用户开启……
互联网“菜场”争夺战互联网买菜风潮掀起,一时间,新平台犹如雨后春笋般冒出,一些互联网巨头也按捺不住纷纷加入其中。“外卖!”4月14日,从公司加班回到家不久的互联网人士王益从外卖小哥的手……