KylinX:A Dynamic Library Operating System for Simplified and Efficient Cloud ~

正文以前

仿佛很久没写过东西了。。刚才一翻,最新文章在1-19,三个月了。。。果真我已经快放弃简书了,不过这儿好歹承载了那么多的回忆,仍是别丢了吧。之后把我翻译的一些论文丢上来算了。。php

正文

~原文我都用CAJviewer识别出来,而且整理过了,有须要的请私信我~ 或者发我邮箱:1184827350@qq.com询问好了。下面我只放中文的内容了,(全篇大部分google翻译,而后人读一遍粗略修改过。有些地方可能仍是不太通顺,不过那就基本表明我也不大懂了。。。)里面还有一些【】里面的内容是我本身作的标注,能够忽略html


Unikernel专门简化LibOS和目标应用到一个独立的单一用途的虚拟机(VM)上运行在Hypervisor上,这被称为(虚拟)设备。 与传统VM相比,Unikernel设备具备更小的内存占用和更低的开销,同时保证了相同的隔离级别。 在缺点方面,Unikernel剥离了其总体设备的流程抽象,从而牺牲了灵活性,效率和适用性。前端

本文探讨了Unikernel设备(强隔离)和流程(高灵活性/高效率)的最佳平衡。 咱们提供KylinX,一个动态库操做系统,经过提供pVM(相似进程的VM)抽象,实现简化和高效的云虚拟化。 pVM将虚拟机Hypervisor做为操做系统,将Unikernel设备做为容许页面级和库级动态映射的进程。linux

  • 在页面级别,KylinX支持pVM fork以及一组用于pVM间通讯(IpC)的API。
  • 在库级别,KylinX支持在运行时连接到Unikernel设备的共享库。

KylinX对潜在威胁实施映射限制。 KylinX能够在大约1.3毫秒内分叉pVM,并在几毫秒内将库连接到正在运行的pVM,二者都与Linux上的进程分支至关(大约1毫秒)。 KylinX IpC的延迟也与UNIX IPC的延迟至关。web

1 介绍

商品云(如EC2 [5])提供了一个公共平台,租户租用虚拟机(VM)来运行他们的应用程序。 这些基于云的VM一般专用于特定的在线应用程序,如大数据分析[24]和游戏服务器[20],并被称为(虚拟)设备[56,64]。 高度专业化的单一用途设备只须要传统操做系统支持的一小部分来运行其容纳的应用程序,而当前的通用操做系统包含普遍的库和功能,造成最终多用户,多应用程序场景。设备的单一用途的使用和传统操做系统的通用设计之间的失配引发的性能和安全性惩罚,使基于设备的服务的部署和安排变得繁琐[62,52],运行效率低[56],并容易受到没必要要的库的影响[27]。后端

这个问题最近推进了Unikernel [56]的设计,这是一个库操做系统(LibOS)架构,旨在实现云中高效安全的设备。 Unikernel将传统操做系统重构为库,并将应用程序二进制和必需库封装成专用的应用镜像,该映像可直接在 Xen [ 30]和KVM [22] 等虚拟机Hypervisor上运行。与传统VM相比,Unikernel设备去掉了未使用的代码:跨域

  • 实现了更小的内存占用
  • 更短的启动时间
  • 更低的开销
  • 同时保证了相同的隔离级别。

虚拟机Hypervisor的稳定接口避免了早期LibOS遇到的硬件兼容性问题[39]。 【Mark: 早期LibOS能够一看】安全

在缺点方面,Unikernel剥离了其静态密封的单片设备的过程提取,所以牺牲了灵活性,效率和适用性。 例如,Unikernel不能支持动态fork,这是传统UNIX应用程序经常使用的多进程抽象的基础; 而且编译时致使的不可变性使得运行时没法管理,例如在线库更新和地址空间随机化。 这种缺陷在很大程度上下降了Unikernel的适用性和性能。服务器

在多任务操做系统中,进程(运行的程序)须要一种方法来建立新进程,例如运行其余程序。Fork及其变种在类Unix系统中一般是这样作的惟一方式。若是进程须要启动另外一个程序的可执行文件,它须要先Fork来建立一个自身的副本。而后由该副本即“子进程*”*调用exec系统调用,用其余程序覆盖自身:中止执行本身以前的程序并执行其余程序。网络

Fork**操做会为子进程建立一个单独的地址空间。子进程拥有父进程全部内存段的精确副本。在现代的UNIX变种中,这遵循出自SunOS-4.0的虚拟内存模型,根据写入时复制语义,物理内存不须要被实际复制。取而代之的是,两个进程的虚拟内存页面可能指向物理内存中的同一个页,直到它们写入该页时,写入才会发生。在用fork配合exec来执行新程序的状况下,此优化很重要。一般来讲,子进程在中止程序运行前会执行一小组有利于其余程序的操做,它可能用到少许的其父进程的数据结构

当一个进程调用fork时,它被认为是父进程,新建立的进程是它的孩子(子进程)。在fork以后,两个进程还运行着相同的程序,都像是调用了该系统调用通常恢复执行。而后它们能够检查调用的返回值肯定其状态:是父进程仍是子进程,以及据此行事。

fork**系统调用在第一个版本的Unix就已存在[1],它借用于更早的GENIE分时系统[2]Fork**是标准化的POSIX的一部分

在本文中,咱们将研究是否存在平衡,以得到Unikernel设备(强隔离)和进程(高灵活性/高效率)的最佳性能。 在虚拟机Hypervisor(Hypervisor)上的应用程序和传统操做系统上的进程之间进行类比,从静态Unikernel向前迈出一步,就有了KylinX,这是一个动态库操做系统,经过提供pVM(process-like VM)抽象来实现简化和高效的云虚拟化。 咱们将虚拟机Hypervisor做为操做系统和容许pVM的页级和库级动态映射的进程同样的应用程序。

【Hypervisor,又称虚拟机器监视器(英语:virtual machine monitor,缩写为 VMM),是用来创建与执行虚拟机器的软件、固件或硬件。 被Hypervisor用来执行一个或多个虚拟机器的电脑称为主体机器(host machine),这些虚拟机器则称为客体机器(guest machine)。hypervisor提供虚拟的做业平台来执行客体操做系统(guest operating systems),负责管理其余客体操做系统的执行阶段;这些客体操做系统,共同分享虚拟化后的硬件资源。】

  • 在页面级别,KylinX支持pVM fork和一组用于inter-pVM communication(IpC)的API,它与传统的UNIX进程间通讯(IPC)兼容。 IpC的安全性经过仅容许从同一个根pVM分叉的相互受信任的pVM之间的IpC获得保证。
  • 在库级别,KylinX支持共享库,动态连接到Unikernel设备,使pVM可以执行(i)在线库更新,在运行时将旧库替换为新库,以及(ii)重用内存域以进行快速启动。 咱们分析动态映射引起的潜在威胁并实施相应的限制。

咱们经过修改MiniOS [14](用C编写的Unikernel LibOS)和Xen'stoolstack实现了基于Xen [30](1型Hypervisor)的KylinX原型。 KylinX能够在大约1.3毫秒内分配pVM,并在几毫秒内将库连接到正在运行的pVM,这二者都与Linux上的进程分支至关(大约1毫秒)。 KylinX IpC的延迟也与UNIX IPC至关。对实际应用程序(包括Redisserver [13]和Web服务器[11])的评估代表,Kylin在保留隔离保证的同时,比静态Unikernel具备更高的适用性和性能。

本文的其他部分安排以下。 第2节介绍了背景和设计选项。第 3 节介绍了具备安全限制的动态定制的KylinX LibOS的设计 。 第4节报告了KylinX原型实现的评估结果。 第5节介绍相关工做。 第6节总结了论文并讨论了将来的工做。

2 背景

2.1 VM ,容器和Picoprocesses

虚拟化和隔离的文献中有几种传统模型:进程,Jails和VM。

  1. OS进程。 进程模型是针对传统的(部分信任)操做系统环境,并提供丰富的ABI(应用程序二进制接口)和交互性,使得它不适合真正的交付给租户。
  2. FreeBSD Jails [47]。 jail模型提供了一种轻量级机制来分离应用程序及其相关策略。它在传统操做系统上运行一个进程,但限制了几个系统调用接口以减小漏洞。
  3. VMs。 VM模型构建隔离边界匹配硬件。 它为guest虚拟机提供了运行完整操做系统的传统兼容性,但对于重复和残留的操做系统组件而言,这是很是昂贵的。

虚拟机(图1(左))已被普遍用于多租户云, 由于它保证了强大的(类型-监督)隔离[55]。 可是,VM的当前虚拟化体系结构很是繁重,包括高级Hypervisor,VM,OS内核,进程,语言运行时( 如glibc [16]和JVM [21]),库和应用程序,它们很复杂,没法再知足商业云的效率要求。

容器(如LXC [9]和Docker [15])利用内核功能来打包和隔离进程。他们最近需求量很大[25,7,6],由于与VM相比它们很轻。可是,容器比在隔离性上比VM更弱,所以它们常常在VM中运行以实现适当的安全保障[58]。

【 Docker容器实现原理及容器隔离性踩坑介绍: http://dockone.io/article/8148

Picoprocesses [38](图1(中))能够被视为具备更强隔离性但更轻量级的容器。他们使用主机操做系统和客户机之间的小型接口来实现LibOS,实现主机ABI并将高级客户机API映射到小接口。 Picoprocesses特别适合客户端软件交付,由于客户端软件须要在各类主机硬件和操做系统组合上运行[38]。它们也能够在hvpervisors上运行【62,32】。

最近对picoprocesses的研究[67,32,54] 经过容许dynamics来从新启动原始静态隔离模型。 例如,Graphene [67]支持picoprocess fork和multi-picoprocess API,而Bascule [32]容许OS-independent扩展附加到运行时的picoprocess。 虽然这些松弛会稀释严格的隔离模型,但它们有效地将picoprocesses的适用范围扩展到更普遍的应用范围。

2.2 Unikernel Appliances

基于进程的虚拟化和隔离技术面临来自用于与主机操做系统交互的普遍内核系统调用API的挑战。例如,进程/线程管理,IPC,网络等.Linux系统调用已达到近400 [3]而且是不断增长,而且系统调用API比VM的ABI( 能够利用硬件内存隔离和CPU环) 更难以保护 [58]。

最近,研究人员提出减小VM,而不是增长进程,以实现安全和高效的云虚拟化。Unikernel [56]专一于单应用程序VM设备[26],并将Exokernel [39]样式的LibOS应用于VM guest虚拟机,以提升性能优点,同时保留1类虚拟机Hypervisor的强隔离保证。它打破了传统的通用虚拟化架构(图1(左)),并将OS功能(例如,设备驱动程序和网络)实现为库。与其余基于Hypervisor的简化虚拟机(如Tiny CoreLinux [19]和OS 0 [ 49])相比,Unikernel仅将应用程序及其必需的库封装到镜像中。

【Mark:Exokernel is an operating system kernel developed by the MIT Parallel and Distributed Operating Systems group,[1] and also a class of similar operating systems.

Operating systems generally present hardware resources to applications through high-level abstractions such as (virtual) file systems. The idea behind exokernels is to force as few abstractions as possible on application developers, enabling them to make as many decisions as possible about hardware abstractions.[2] Exokernels are tiny, since functionality is limited to ensuring protection and multiplexing of resources, which is considerably simpler than conventional microkernels' implementation of message passing and monolithic kernels' implementation of high-level abstractions.

Implemented applications are called library operating systems; they may request specific memory addresses, disk blocks, etc. The kernel only ensures that the requested resource is free, and the application is allowed to access it. This low-level hardware access allows the programmer to implement custom abstractions, and omit unnecessary ones, most commonly to improve a program's performance. It also allows programmers to choose what level of abstraction they want, high, or low.

Exokernels can be seen as an application of the end-to-end principle to operating systems, in that they do not force an application program to layer its abstractions on top of other abstractions that were designed with different requirements in mind. For example, in the MIT Exokernel project, the Cheetah web server stores preformatted Internet Protocol packets on the disk, the kernel provides safe access to the disk by preventing unauthorized reading and writing, but how the disk is abstracted is up to the application or the libraries the application uses. https://en.wikipedia.org/wiki/Exokernel*】*

l 【类型I:本地或裸机Hypervisor

l 类型II:Hosted Hypervisor】

因为Hypervisor已经提供了传统操做系统的许多管理功能(例如隔离和调度) ,所以Unikernel采用了(minimalism philosophy)极简主义哲学[36],它不只经过删除没必要要的库并且还从其LibOS中剥离了重复的管理功能来最小化VM。 例如,Mirage[57]遵循多核模型[31]并利用虚拟机Hypervisor进行多核调度,使单线程运行时能够具备快速的顺序性能; MiniOS [14]依赖于Hypervisor( 而不是in-LibOS连接器)来加载/连接设备启动时间; 而LightVM [58]经过从新设计Xen的控制平面实现了快速VM启动。

2.3 动机和设计选择

Unikernel设备和传统的UNIX进程能够抽象出隔离,特权和执行状态的单元,并提供内存映射,执行协做和调度等管理功能。为了实现低内存占用和小型计算基础(TCB),Unikernel剥离了其单片设备的进程抽象,并将简约LibOS与其目标应用程序相连接,展现了依靠虚拟机Hypervisor消除重复功能的好处。但在缺点方面,进程和编译时肯定的总体性大大下降了Unikernel的灵活性,效率和适用性。

【TCB是Trusted Computing Base的简称,指的是计算机内保护装置的整体,包括硬件、固件、软件和负责执行安全策略的组合体。它创建了一个基本的保护环境并提供一个可信计算机系统所要求的附加用户服务。】

如图1(右)所示,KylinX经过将虚拟机Hypervisor显式为一个OS,而将Unikernel设备做为进程显式提供pVM抽象。 KylinX轻松放松了Unikernel的编译时单片性要求,容许页面级和库级动态映射,这样pVM就能够拥有Unikernel设备和UNIX进程的最佳性能。如表1所示,KylinX能够被视为对Unikernel的扩展(提供pVM抽象),相似于Graphene [67](提供传统的多工艺兼容性)和 Bascule [ 32](提供运行时可扩展性)的扩展到picoorocess。

出于如下缘由,咱们在Hypervisor而不是guestLibOS中实现KylinX的动态映射扩展。

  1. 首先,guestLibOS外部的扩展容许Hypervisor强制执行映射限制(第 3.2.3节和第3.3.3节),从而提升安全性。

  2. 其次,Hypervisor更灵活地实现动态管理,例如,在pVM的在线库更新期间恢复实时状态(第3.3.2节)。

  3. 第三,KylinX很天然地遵循Unikernel的极简主义哲学(第2.2章),利用虚拟机Hypervisor来消除重复的客户LibOS功能。

向后兼容性是另外一种权衡。 最初的Mirage Unikernel [56]占据了一个极端的位置,现有的应用程序和库必须在OCaml [10]中彻底重写,以确保类型安全,这须要大量的工程工做,并可能引入新漏洞。 相比之下,KylinX旨在支持源代码(主要是C)兼容性,所以能够在KylinX上运行各类各样的遗留应用程序,只需最少的调整工做。

威胁模型。 KylinX采用传统的威胁模型[56,49],与Unikernel相同的上下文[ 56],其中 VM/pVM 在虚拟机Hypervisor上运行,而且有望在公共多租户云中提供面向网络的服务。 咱们假设攻击者能够在VM/pVM中运行不受信任的代码,而且在VM/pVM中运行的应用程序受到来自同一云中的其余人和来自经过Internet链接的恶意主机的潜在威胁。KylinX将虚拟机Hypervisor(使用其工具堆栈)和控制域(dom0)视为TCB的一部分,并利用虚拟机Hypervisor隔离其余租户的攻击。使用SSL和SSH等安全协议有助于KylinX pVM对外部实体进行信任。

www.ibm.com/developerwo…

------------------------------------------------------------------------------

Dom0 is the initial domain started by the Xen hypervisor on boot. Dom0 is an abbrevation of "Domain 0" (sometimes written as "domain zero" or the "host domain"). Dom0 is a privileged domain that starts first and manages the DomU unprivileged domains. The Xen hypervisor is not usable without Dom0

A DomU is the counterpart to Dom0; it is an unprivileged domain with (by default) no access to the hardware. It must run a FrontendDriver for multiplexed hardware it wishes to share with other domains. A DomU is started by running

英特尔软件Guard eXtensions(SGX)[12]等硬件的最新进展证实了屏蔽执行的可行性,并以保护VM/pVM免受特权虚拟机Hypervisor和dom0 [33,28,45]破坏的可行性,这将在咱们将来的工做中进行研究。 咱们还假设硬件设备没有受到损害,尽管已经肯定了硬件威胁[34]。

3 KylinX 设计

3.1概述

KylinX扩展了Unikernel,以实现之前仅适用于进程的理想功能。咱们不是从零开始设计一个新的LibOS,而是基于MiniOS构建KylinX [27],这是一个在Xen虚拟机Hypervisor上运行的用户VM域(domU)的C风格Unikernel LibOS. MiniOS 使用其前端驱动程序访问硬件,链接到相应的硬件特权dom0或专用驱动程序域中的后端驱动程序.MiniOS具备单个地址空间,没有内核和用户空间分隔,也没有抢占的简单调度程序。 MiniOS很小巧但适合在Xen上采用整洁高效的LibOS设计。 例如,Erlang on Xen [1],LuaJIT [2],C1ickOS [59]和LightVM [58]分别利用MiniOS提供 Erlang,Lua ,Click和快速启动环境。 【Marked:Xen虚拟化基本原理详解 blog.51cto.com/wzlinux/172… Mini-OS: wiki.xenproject.org/wiki/Mini-O…

如图2所示,基于MiniOS的KylinX设计包括(i)DomO中Xen工具堆栈的(受限制的)动态页面/库映射扩展,以及(ii)进程抽象支持(包括动态pVMfork/IpC和运行时pVM)库连接)在DomU。

3.2 动态页面映射

KylinX经过利用Xen的共享内存和受权表来执行跨域页面映射,从而支持进程式设备分支和通讯。

3.2.1 pVM Fork

fork API是实现pVM传统多进程抽象的基础。 KylinX将每一个用户域(pVM)视为一个进程,当应用程序调用fork()时,将生成一个新的pVM。

咱们利用Xen的内存共享机制实现fork操做,它经过 (i)复制xc_dom_image结构 (ii)调用Xen的unpause()API来分叉调用父pVM并将其域ID返回给父级来建立child pVM。

如图3所示,当在父pVM中调用fork() 时,咱们使用内联汇编来获取CPU寄存器的当前状态并将它们传递给子寄存器。控制域(dom0)负责分支和启动子pVM。 咱们修改libxc以在建立父pVM时将xc_dom_images结构保留在内存中,这样当调用fork()时,结构能够直接映射到子pVM的虚拟地址空间,而后父进程可使用受权表与子进程进行共享。以可写数据以写时复制(CoW)方式共享。 【Copy-on-write (CoW or COW), sometimes referred to as implicit sharing[1] or shadowing,[2] is a resource-management technique used in computer programming to efficiently implement a "duplicate" or "copy" operation on modifiable resources.[3] If a resource is duplicated but not modified, it is not necessary to create a new resource; the resource can be shared between the copy and the original. Modifications must still create a copy, hence the technique: the copy operation is deferred to the first write. By sharing resources in this way, it is possible to significantly reduce the resource consumption of unmodified copies, while adding a small overhead to resource-modifying operations. 若是资源重复但未修改,则无需建立新资源; 资源能够在副本和原始文件之间共享。 修改必须仍然建立一个副本,所以技术:复制操做被推迟到第一次写入。 经过以这种方式共享资源,能够显着减小未修改副本的资源消耗,同时为资源修改操做增长一小部分开销 en.wikipedia.org/wiki/Copy-o…

经过unpause()启动子pVM以后,它(i)接受来自其父级的共享页面,(ii)恢复CPU寄存器并跳转到fork以后的下一条指令,以及(iii)开始做为子级运行。在完成fork()以后 ,KylinX异步初始化一个事件通道并在父子pVM之间共享专用页面以启用它们的IpC,以下一小节中所介绍的。

3.2.2 inter-pVM通讯(IpC)

KylinX提供了一个多进程(多pVM)应用程序,其全部进程(pVM)都在OS(Hypervisor)上协同运行。目前,KylinX遵循严格的隔离模型[67],其中只有相互信任的pVM才能相互通讯,这将在第3.2.3中详细讨论。

两个通讯pVM使用事件通道共享页面来实现pVM间通讯。若是两个相互信任的pVM在第一次通讯时还没有初始化事件通道,由于它们没有经过fork()产生的父子关系(3.2.1),那么KylinX将:

  • 验证其相互适应性(第3.2.3节,必须是一个family的)
  • 初始化事件通道
  • 在它们之间共享专用页面。

事件通道用于通知事件,共享页面用于实现通讯。 KylinX已经实现了如下四种类型的inter-pVM通讯API(在表2中列出)。

  • (1)pipe(fd)建立一个管道并返回两个文件描述符(fd [0]和fd [1]),一个用于写入,另外一个用于读取。
  • (2)kill( domid,SIG )经过将SIG写入共享页面并通知目标pVM(domid)从该页面读取信号,将信号(SIG)发送到另外一个pVM(domid); exit和wait是使用kill实现的。
  • (3) ftok( path,projid)将path和proj id转换为IpC密钥,这将由msgget(key,msgflg)用于建立带有标志的消息队列(msgflg)并返回队列ID(msgid); msgsend (msgid,msg,len)和msgrcv(msgid,msg,len)使用长度len写入/读取队列(msgid)到/来自msmbuf结构(msg)。
  • (4)shmget(key,size,shmflg)使用键(key),内存大小(size)和flag(shmflg)建立并存储一个内存区域,并返回共享内存区域ID(shmid),它能够附加和分离到shmat(shmid,shmaddr,shmflg)和shmdt(shmaddr)。

3.2.3 动态页面映射限制

在执行动态pVM fork时,父pVM将页面分享给空的子pVM ,该过程不会引入新的威胁。

在执行IpC时,KylinX经过抽象相互信任的pVM 来保证安全性,这些pVM是从同一个根pVM分叉的。例如,若是pVM A分支pVM B,它进一步分叉另外一个pVM C,那么三个pVM A,B和C属于同一个家庭。为简单起见,目前KylinX遵循all-all-nothing隔离模型:只有属于同一系列的pVM才被认为是可信的而且容许彼此通讯。 KylinX拒毫不受信任的pVM之间的通讯请求。

3.3 动态库映射

3.3.1 pVM库连接

继承自MiniOS,KylinX具备单个平面虚拟存储器地址空间,其中应用程序二进制和库,系统库(用于引导程序,内存分配等)和数据结构共同定位以运行。 KylinX将一个动态段加入MiniOS的原始内存布局中,以便在加载后适应动态库。

如图2所示,咱们在Xen控件库(libxc)中实现了动态库映射机制,它由上层工具栈使用,例如xm/xl/chaos。 pVM其实是一个准虚拟化domU,它

  • 建立一个域,
  • 解析kernel image文件
  • 初始化启动内存,
  • 在内存中构建映像
  • 启动映像的domU。

在上面的第4步中,咱们经过扩展libxc的静态连接过程,添加一个函数(xc_dom_map_dyn())来将共享库映射到动态段中,以下所示。

  1. 首先 ,KylinX从设备映像的程序头表中读取共享库的地址,偏移量,文件大小和内存大小。
  2. 第二 ,它验证是否知足限制(第3.3.4节KylinX强制限制库的身份以及库的加载器)。 若是不是,则程序终止。
  3. 第三 ,对于每一个动态库,KylinX检索其 动态部分的信息,包括动态字符串表,符号表等。
  4. 第四 ,KylinX将整个依赖树中的全部必需库映射到pVM的动态段,当实际访问时,它将惰性地将未解析的符号重定位到正确的虚拟地址。
  5. 最后 ,它跳转到pVM的入口点。

KylinX在实际使用以前不会加载/连接共享库,这相似于传统进程的延迟绑定[ 17]。所以,KylinX pVM的启动时间低于之前的Unikernel VM。 此外,与以前仅支持静态库的Unikernel相比,使用共享库的KylinX的另外一个优点是它有效地减小了高密度部署中的内存占用(例如,LightVM [58]中的每台机器8K VM和每台机器80K容器)在Flurries [71]中,这是限制可扩展性和性能的惟一最大因素[58]。

【Mark:动态连接和延迟绑定:www.jianshu.com/p/20faf72e0…

接下来,咱们 将讨论KylinX AVM的动态库映射的两个简单应用。

3.3.2 在线 pVM库更新 保持系统/应用程序库的最新版本以修复错误和漏洞很是重要。 静态Unikernel [56]必须从新编译并从新启动整个设备映像才能为其每一个库应用更新 ,这可能会致使设备拥有许多第三方库时出现大量部署负担。

在线库更新比滚动启动更有吸引力,主要是保持与客户端的链接。首先,当服务器有许多长期链接时,从新启动将致使高从新链接开销。其次,不肯定第三方客户端是否会从新创建链接,这会在从新启动后为从新链接施加复杂的设计逻辑。第三,频繁重启和从新链接可能会严重下降关键应用程序的性能,如高频交易。

动态映射使KylinX能够实如今线库更新。 可是,库可能有本身的状态,例如压缩或加密,所以简单地替换无状态函数不能知足KylinX的要求。

像大多数库更新机制(包括DYMOS [51],Ksplice [29],Ginseng [61],PoLUS [37 ],Katana [63],Kitsune [41]等),KylinX要求新旧库与二进制兼容:容许向库中添加新函数和变量,但不容许更改函数接口,删除函数/变量或更改结构字段。对于库状态,咱们指望全部状态都存储为在更新期间将被保存和恢复的变量(或动态分配的结构)。

KylinX提供了更新(domid,new_lib,old_lib)API,能够动态地将old_lib和new_lib替换为domU pVM(ID = domid),并具备必要的库状态更新。 咱们还提供了一个更新命令“update domid,new_lib,old_lib” 用于解析参数并调用update() API。

动态pVM更新的难点在于在密封的VM设备中操做符号表。 咱们利用dom0来解决这个问题。 当调用更新API时,dom0将 (i)将新库映射到dom0的虚拟地址空间; (ii)与domU共享装载的库; (iii)经过要求domU检查domU的每一个内核线程的调用堆栈来验证旧库是否静止; (iv)等到旧库未被使用并暂停执行; (v)将受影响的符号条目修改成适当的地址; 最后 (vi)释放旧库。 在上述第五步中,有两种符号(函数和变量)将以下所述进行解析。

函数。 函数的动态解析过程如图4所示。咱们将重定位表,符号表和字符串表保存在dom0中,由于它们不在可加载段中。 咱们在dom0中加载全局偏移表函数(.got.plt )和过程连接表(.plt)并与domU共享它们。 为了在不一样的域中解析符号,咱们在.plt 表的第1st个条目中修改了2nd的汇编行 (如图4中的蓝色区域所示),以指向KylinX的符号解析函数(du_resolve)。 在加载新的库(new_lib)以后,将old_lib中的每一个函数输入 .got.plt表(例如,图4中的foo)被修改成指向.plt表中的相应条目,即图4中虚线绿线所示的2nd组件(push n)。当一个函数(在new_lib加载后第一次调用库的foo),将使用两个参数( n (got + 4)) 调用du_resolve ,其中n是.got.plt表中符号(foo)的偏移量和(got+ 4)是当前模块的ID。 而后du_resolve要求dom0调用对应的d0_resolve,它在new_lib中找到foo,并将当前模块的gt.plt表中的相应条目(由n定位)更新为foo的正确地址(图中的蓝线) 4)。

变量。 变量的动态分辨率略微复杂。 目前咱们只是假设new_libexpect将其全部变量设置为它们的实时状态inold_lib而不是它们的初始值。 若是没有这个限制,编译器将须要扩展以容许开发人员为每一个变量指定他们的意图。

(1)全局变量。 若是在主程序中访问了库的全局变量(g),则g存储在程序的数据段 (.bss )中,而且在指向g的库的全局偏移表(.got)中存在条目,所以加载new_lib后,KylinX会将new_lib的.got表中的g条目解析为g的正确地址。 不然,g存储在库的数据段中,所以KylinX负责将全局变量g从old_lib复制到new_lib。

(2)静态变量。 因为静态变量存储在库的数据段中而且没法从外部访问,所以在加载new_1 ib以后,KylinX将简单地将它们从old_lib逐个复制到new_lib。

(3)指针。 若是库指针(p)指向动态分配的结构,那么KylinX会预先设置结构并将new_lib中的p设置为它。 若是p指向存储在程序数据段中的全局变量,那么p将从old_lib复制到new_lib。 若是指向静态变量(或存储在库中的全局变量),则p将指向新地址。

3.3.3 pVM 回收

KylinX pVM和Unikernel VM [58]的标准启动(第3.3.1节)相对较慢。 正如评估的第4章所述,启动pVM或UnikernelVM须要100多毫秒,大部分时间用于建立空域。 所以,咱们为KylinX pVM设计了一个pVM回收机制,利用动态库映射来绕过域建立。

回收的基本思想是重用一个内存空域来动态地将应用程序(做为共享库)映射到该域。 具体来讲,在调用占位符动态库的app_entry函数以前,会检查一个空的可回收的域并等待运行应用程序。使用app_entry做为条目,将应用程序编译为共享库而不是可引导映像。为了加速应用程序的pVM引导,KylinX恢复了被检查的域,并经过在在线更新过程以后替换占位符库来连接应用程序库(第3.3.2节)。

3.3.4 动态库映射限制

与执行动态库映射时静态和单片密封的Unikernel相比,KylinX应该隔离任何新的漏洞。 主要的威胁是攻击者可能会将恶意库加载到pVM的地址空间,用具备相同名称和符号的受损库替换库,或者将共享库的符号表中的条目修改成伪符号/函数。

***【Linux进程地址空间学习: ***

http://www.choudan.net/2013/10/24/Linux%E8%BF%9B%E7%A8%8B%E5%9C%B0%E5%9D%80%E7%A9%BA%E9%97%B4%E5%AD%A6%E4%B9%A0***(%E4%B8%80).html******】***

为了解决这些威胁,KylinX强制限制库的身份以及库的加载器。 KylinX支持开发人员指定动态库的签名,版本和加载器的限制,这些限制存储在pVM映像的标头中,并在连接库以前进行验证。

**签名和版本。**库开发人员首先生成库的SHA1摘要,该摘要将由RSA(Rivest-Shamir-Adleman)加密。 结果保存在动态库的asignature部分中。 若是设备须要对库进行签名验证,则KylinX将使用公钥读取并验证签名部分。一样要求并验证版本限制。

装载机。 开发人员能够在库的加载器上请求不一样级别的限制:(i)仅容许pVM自己做为加载器; (ii)还容许同一申请的其余pVM; 或(iii)甚至容许其余应用程序的pVM。 经过前两个限制,一个受损应用程序中的恶意库不会影响其余应用程序。 加载程序检查的另外一种状况是将应用程序二进制文件做为库并将其连接到pVM以进行快速回收(第3.3.3节),其中KylinX将加载程序限制为空pVM。

有了这些限制,与静态密封的Unikernel相比,KylinX没有引入任何新的威胁。 例如,pVM的运行时库更新(第3.3.2节)对签名(做为可信开发人员 ),版本 (做为特定版本号)和加载器(做为pVM自己)具备限制,将具备相同的级别安全保障从新编译和从新启动。

4 评估

咱们在Ubuntu 16.04和Xen上实现了KylinX的原型。 按照MiniOS [14]的默认设置,咱们分别使用RedHat Newlib和1wIP做为libc/libm库和TCP/IP堆栈。咱们的试验台有两台机器,每台机器都配有Intel 6 core Xeon ES-2640 CPU,128 GB RAM和一台1 Gb ENIC。

咱们已经向KylinX移植了一些应用程序,其中咱们将使用多进程Redis服务器[13]以及多线程Web服务器[11]在4.6章中来评估KylinX的应用程序性能。 因为MiniOS和RedHat Newlib的限制,目前须要进行两种调整才能将应用程序移植到KylinX。 首先,KylinX只能支持select而不是更高效的epoll。 其次,进程间通讯(IPC)仅限于表2中列出的API。

4.1 标准启动

咱们评估 KylinX pVM 的标准启动过程( 3.3.1)的时间,并将其与全部运行Redis服务器的MiniOS VM和Docker容器进行比较。 Redis是一个内存中的键值存储,支持快速键值存储/查询。 每一个键值对由固定长度键和可变长度值组成。它使用单线程进程来提供用户请求,并经过分配新的备份过程来实现(按期)序列化。

咱们禁用Xen Store日志记录以消除按期日志文件刷新的干扰。RedHat Newlib的C库(libc)在嵌入式系统中是静态的,很难转换为共享库。简单来讲,咱们将libc编译成静态库和libyn( Newlib的数学库)到一个共享库中,该库将在运行时连接到KylinX pVM。因为Mini不能支持fork,咱们(暂时)删除此实验中的相应代码。

启动单个KylinX pVM大约须要124毫秒,能够大体分为两个阶段,即在内存中建立域/映像(步骤1~4,第3.2.1节),以及引导映像(步骤5)。动态映射在第一阶段执行。大多数 时间(大约121毫秒)花费在第一阶段,这会调用高级调用来与Hypervisor进行交互。第二阶段启动pVM大约须要3毫秒。在此相反,MiniOS大约须要133毫秒启动一个虚拟机,而Docker 须要花费约210毫秒开始创建容器。 KylinX比MiniOS花费的时间更短,主要是由于在引导期间不会读取/连接共享库。

而后,咱们评估在一台机器上顺序启动大量(最多1K)pVM的总时间。咱们还评估了MiniOS VM和Docker容器的总启动时间,以便进行比较。

结果如图5所示。首先,因为延迟加载/连接,KylinX比MiniOS快得多。其次,MiniOS和KylinX的启动时间随着VM/pVM数量的增长而线性增长,而Docker容器的启动时间只是线性增长,这主要是由于XenStore在服务大量的VM/pVM时效率很低。

4.2 fork和回收

与容器相比,因为XenStore效率很高,KylinX的标准启动没法很好地扩展到大量pVM。最近,LightVM [58]经过实现chaos/libchaos,noxs(无XenStore)和拆分工具堆栈以及许多其余优化来彻底从新设计Xen的控制平面,从而实现大量VM的ms级启动时间。咱们采用LightVM的nox来消除XenStore的影响,并测试运行未经修改的Redis仿真传统进程分支的pVM fork机制。 LightVM的noxs使KylinX pVM的启动时间即便对于大量pVM也能线性增长。单个pVM的fork大约须要1.3毫秒(未显示缺乏空间),比LightVM的原始启动过程快几倍(约4.5毫秒)。KylinX pVM 的fork比 Ubuntu上的进程fork(大约1 ms)略慢,由于包括页面共享和参数传递在内的多个操做很是耗时。请注意,父/子pVM的事件通道和共享页的初始化是异步执行的,所以不计入fork的延迟。

4.3 内存占用

咱们在一台机器上测量不一样数量的pVM/VM/容器的KylinX,MiniOS和Docker(Running Redis)的内存占用量。结果(如图6所示)证实,与静态密封的MiniOS和Docker容器相比,KylinX pVM具备更小的存储空间。这是由于KylinX容许同一个应用程序( 第3.3章) 的全部设备共享库(libc除外),所以共享库最多须要加载一次。内存占用优点促进了虚拟化[42],可用于在VM设备之间动态共享物理内存,并使KylinX可以实现与页面级重复数据删除[40]至关的内存效率,同时下降复杂性。

4.4 Inter-pVM通讯

咱们经过分配父pVM并测量父/子通讯延迟来评估pVM间通讯(IpC)的性能。咱们将一对父/子pVM称为线性pVM。正如引言第3.2.1节所述,两个线性pVM已经有一个事件通道共享页面,所以它们能够直接与其余页面进行通讯。相反,非线性pVM对必须在第一次通讯以前初始化事件通道和共享页面。

结果列于表3中,咱们将其与Ubuntu上相应的IPC进行比较。因为Xen的高性能事件通道和共享内存机制,两个线性pVM之间的KylinX IpC延迟与Ubuntu上相应的IPC延迟至关。请注意,pipe的延迟不只包括建立管道,还包括经过管道写入和读取值。因为初始化成本的缘由,非线性pVM之间的首次通讯延迟要高出几倍。

4.5 运行时库更新 咱们经过使用较新版本(RedHat Newlib 1.18)动态替换默认libyn(RedHat Newlib 1.16)来评估KylinX的运行时库更新。libyn是MiniOS / KylinX使用的数学库,包含110个基本数学函数的集合。

为了测试KylinX对全局变量的更新过程,咱们还向旧的和新的libyn库添加了111个伪全局变量以及一个read_global函数(读出全部全局变量)。主函数首先将全局变量设置为随机值,而后经过调用读取全局函数按期验证这些变量。

所以,在咱们的测试中总共有111个函数和111个变量须要更新。更新程序大体可分为 4个阶段,咱们测量每一个阶段的执行时间。

首先,KylinX将new_lib加载到dom0的内存中并与domU共享。其次,KylinX修改.got.plt表中函数的相关条目,以指向.plt表中的相应条目。 第三,KylinX 为每一个函数调用du_resolve,这些函数要求dom0解析给定的函数并返回其在new_lib中的地址,而后将相应的条目更新为返回的地址。最后,KylinX将新lib的.got表中的全局变量的相应条目解析为适当的地址。咱们在评估中修改第三阶段,一次更新libyn中的全部111个函数,而不是在实际被调用时懒惰地连接函数(第3.3.2节),以便概述libyn的整个运行时更新成本。

结果如图7所示,其中更新全部函数和变量的总开销约为5毫秒。第三阶段(解析函数)的开销高于其余阶段,包括第四阶段(解析变量),这是由第三阶段中的几个耗时的操做引发的,包括解析符号,跨域调用d0_ resolve,返回实际函数地址和更新相应的条目。

4.6 申请

除了pVM调度和管理的流程灵活性和效率以外,KylinX还为其容纳的应用程序提供了高性能,与Ubuntu上的对应应用程序至关,如本小节所述。

4.6.1 Redis 服务器应用程序

咱们在KylinX pVM中评估Redis服务器的性能,并将其与MiniOS/Ubuntu中的性能进行比较。一样,因为MiniOS不支持fork(),咱们暂时删除了序列化代码。 Redis服务器使用select而不是epoll来实现异步I/O,由于 MiniOS和KylinX使用的lwIP堆栈[4]尚不支持epoll。

咱们使用Redis基准[13]来评估性能,该性能使用可配置数量的繁忙循环来异步写入KV。咱们为客户端的写请求运行不一样数量的pVM/VM/进程(1个服务器一个)。咱们测量写入吞吐量做为服务器数量的函数(图8)。三种Redis服务器具备类似的写入吞吐量(因为选择的限制),随着并发服务器的数量几乎线性增长(在lwIP堆栈成为瓶颈以前,缩放是线性的,最多8个实例)。

4.6.2 Web 服务器应用程序

咱们评估了KylinX中的JOS Web服务器[11],它为多个链接提供多线程处理。主线程接受传入链接后,Web服务器建立工做线程来解析标头,读取文件,并将内容发送回客户端。咱们使用Weighttp基准测试来支持HTTP协议的一小部分(但对咱们的Web服务器来讲足够)来衡量Web服务器性能。与Redis服务器的评估相似,咱们经过在一台计算机上运行多个Weighttp [8]客户端来测试Web服务器,每一个客户端不断向Web服务器发送GET请求。

咱们将吞吐量做为并发客户端数量的函数进行评估,并将其与分别在MiniOS和Ubuntu上运行的Web服务器进行比较。结果如图9所示,其中KylinX web服务器实现了比MiniOS web服务器更高的吞吐量,由于它提供更高的顺序性能。KylinX和MiniOS Web服务器都比Ubuntu Web服务器慢,由于异步选择是使用MiniOS的网络驱动程序[27}进行低效调度的。

5 相关工做

KylinX与静态Unikernel设备[56,27 ],减小 VM [ 19,48,49 ],容器[66,9,15]和图像处理[38,62,32,54,67,33]有关。

5.1 Unikernel 和Redced VMs

KylinX是Unikernel[56]的扩展,在MiniOS [27]之上实现。Unikernel OS包括Mirage [56],Jitsu [55],Unikraft [18]等。 例如,Jitsu [55]利用Mirage [56]设计一个功能强大且响应迅速的平台,用于在边缘网络中托管云服务。LightVM [58]利用Xen上的Unikernel来实现快速启动。

MiniOS [27]设计并实现了一个C风格的Unikernel LibOS,它做为Xen域中的半虚拟客户OS运行。MiniOS具备比Mirage更好的向后兼容性,并支持用C语言编写的单进程应用程序。可是,最初的MiniOS静态密封设备而且遇到与其余静态Unikernel类似的问题。

KylinX和静态 Unikernels( 如Mirage [56],MiniOS [27]和EbbRT [65])之间的区别在于pVM抽象,它明确地将hypervisoras做为操做系统并支持过程式操做,如pVM fork/IpC和动态库映射。映射限制(第3.3.4节)使KylinX尽量地引入漏洞,而且没有比 Mirage/MiniOS 更大的TCB [56,55]。 KylinX支持源代码(C)兼容性,而不是使用类型安全的语言来重写整个软件堆栈[56]。

最近的研究 [19,49,48]试图改进基于Hypervisor的类型1虚拟机,以实现更小的内存占用,更短的启动时间和更高的执行性能。 Tiny Core Linux [19]尽量减小现有的Linux发行版,以减小客户的开销。 0S0 [49]实现了一个新的客户操做系统,用于在VM上运行单个应用程序,解析对其内核的libc函数调用,该内核采用优化技术,如spinlock-freemutex [70]和网络通道网络堆栈[46 ] .RumpKernel [48]经过实现优化的客户操做系统来减小VM。与KylinX不一样,这些通用LibOS设计包含针对目标应用的没必要要的特征,致使更大的攻击面。它们不支持多进程抽象。此外,KylinX的pVM fork比SnowFlock中基于重复的VM_fork要快得多[50]。

5.2 容器

容器使用操做系统级虚拟化[66]和利用内核功能来打包和隔离进程,而不是依赖于虚拟机Hypervisor。做为回报,他们不须要捕获系统调用或模拟硬件,而且能够做为正常的OS进程运行。例如,Linux Containers(LXC)[9]和Docker [15]经过使用许多Linux内核功能(例如naynespaces和cgroups)来建立容器,以打包资源并运行基于容器的进程。

容器须要使用相同的主机操做系统API [49],从而暴露数百个系统调用并扩大主机的攻击面。所以,尽管LXC和Docker容器一般比传统VM更有效,但它们提供的安全性较低,由于攻击者可能会破坏容器内运行的进程。

5.3 Picoprocess

picoprocess本质上是一个容器,它在主机操做系统和客户机之间实现LibOS,将高级客户机API映射到一个小接口上。原始的picoprocess设计(Xax [38]和Embassies [43])只容许一个微小的系统调用API ,它能够小到使人信服(甚至能够证明)的孤立。 Howell等。经过提供POSIX 仿真层并绑定现有程序,展现如何在最小的picoprocess接口[44]之上支持一小组单进程应用程序。

最近的研究放松了静态和刚性微过程隔离模型。。例如,Drawbridge [62]是Xax [38] picoprocess的WinBows转换,并建立了支持丰富桌面应用程序的picoprocess LibOS。 Graphene [67]扩展了LibOS范式,支持在picoprocesses的一个家族(沙箱)中使用多进程API(使用消息传递)。 Bascule [ 32]容许 在运行时安全有效地附加与OS无关的扩展。 Tardigrade [54]使用picoprocesses轻松构建容错服务。这些松弛在picoprocess上的成功激发了咱们对Unikernel的动态KylinX扩展。

容器和picoprocesses一般具备大的TCB,由于LibOS包含未使用的功能。相比之下,KylinX和其余Unikernel利用虚拟机Hypervisor的虚拟硬件抽象来简化它们的实现,并遵循极简主义[36]仅将应用程序与必需的库相结合,不只提升了效率,还提升了安全性。

Dune [34]利用Intel VT-x [69]提供进程(而不是机器)抽象来隔离进程并访问特权硬件功能。IX [ 35]将 虚拟设备整合到Dune过程模式中,为网络系统实现了高吞吐量和低延迟。1wCs [53]在进程内提供独立的保护,特权和执行状态单元。

与这些技术相比,KylinX直接运行Xen(1型虚拟机Hypervisor),天然提供强大的隔离,使KylinX可以专一于灵活性和效率问题。

6 结论

在云虚拟化的文献中,长期存在强烈孤立和丰富特征之间的紧张关系。本文利用新的设计空间,经过在高度专用的静态Unikernel中添加两个新特性(动态页面和库映射)来提出pVM抽象。简化的虚拟化架构(KylinX)将虚拟机Hypervisor做为OS,并安全地支持灵活的进程式操做,例如pVM fork和inter-pVM通讯,运行时更新和快速回收。

在将来,咱们将经过模块化[27],分解[60]和新交所飞地[33,28,45,68] 来提升安全性。咱们将经过采用更高效的运行时MUSL来改善KylinX的性能[23],并使KylinX适应Multi LibOS model [65],容许将pVM跨越多个机器。目前,pVM的回收机制仍是暂时的和有条件的:它只能检查点的空域; 循环的pVM没法使用事件通道或共享内存与其余pVM通讯; 应用程序只能采用自包含共享库的形式,不须要加载其余共享库; 回收后,新老pVM之间仍然没有检查潜在安全威胁的保障措施。咱们将在将来的工做中解决这些缺点。

7 致谢

这项工做获得了中国国家基础研究计划(2014CB340303)和国家天然科学基金(61772541)的支持。Wethank Li Ziyang Li,Qiao Zhou和匿名评论员帮助他们完善了本文。这项工做是在第一做者访问剑桥大学计算机实验室的NetOS小组时进行的,咱们感谢Anil Madhavapeddy 教授,Ripduman Sohan和刘浩的讨论。

正文以后

搞掂,但愿有用吧。。这些新点的文章网络上屁内容都没得,国防科技大学的老师也没得对外的联系方式,因此说,选了这篇文章作汇报的同窗,加油~

相关文章
相关标签/搜索