Single address spaces: design flaw or feature? part1

来源:互联网 发布:nginx配置ip端口访问 编辑:程序博客网 时间:2024/06/10 19:22
unikernel运行与单地址空间, 这个地址通常有hypervisor提供, 但是并没有推荐你不能运行单个unikernel在裸的cpu上(虚拟化的情况下)。 伴随着unikernel被越来越多的人熟悉, 我看到一些人提出单地址的设计
的选择并不好。 不幸的是,许多unikernel的文章的并没有充分解释清楚单地址在MMU中的有点。 接下来第一部分我会解释使用单地址的性能有点和一些高性能的non-unikernel系统正设计来使用单地址。 第二部分探索单地址模式的安全性/正确性。
大多数os使用MMU来实现不同进程之间的隔离包括用户态与内核态之间。 MMU-enforced隔离是非常有效的工具, 如果你熟悉你的MMU硬件体系(说白了就是怎么从程序中的逻辑地址转换成物理地址,通过一个地址转换表实现),通过这个体系就可以实现不同进程之间或者用户态与内核态的资源隔离。在内核以外比如进程间通信,这个隔离的性是由MMU配置产生的(对于用户程序是透明的)。
MMU提供恶意的未知代码的资源隔离,但是有损耗(没懂什么意思)。 上下文切换需要花费时间。
1: MMU表可能会修改。
2: TLB变为无效。
3: cpu指令或者data cache维护(cache会自己调整)
4: 寄存器状态需要保持和恢复
5: 管道也许需要flushed/reloaded


上下文切换的性能非常重要,每次系统调用至少需要两次上下文切换(userspace-to-kernel, kernel-t-userspace)

上下文切换破坏你的caches。。。

虽然有硬件机制来优化上下文切换, 但并不能消除所有的性能退化。 上下文切换的额外的消耗时间是切换自己(所有先前的cache被完全损坏)。 这些代码在切换后需要重新解析(当前cache的已经损坏,需要重新从内存中获取,cpu cycle变得非常大), 这是非常消耗性能的。 这个需要花费成千上万个cpu cycles来恢复到以前的状态。 执行一个系统调用write()会逐出2/3的L1 cache和TLB。 大大减低用户代码性能决定于多少执行发送在syscall上面。 
硬件的一切特性可以坚持cache的污染。 TLB lockdown机制, 比如,允许OS保存一定数量的TLB不变。再比如, 内核可以检索自己的地址空间来减少TLB污染。 但是这些特性不能完全解决上下文切换中的应用程序的性能损失。
Lock down 一些TLB不被污染可以让上下文切换没损失吗? 除非你的TLB固定所有当前程序的cache,切换后程序会从你固定的TLB查找数据。
上切换切换必然会导致cache污染, cpu 需要巧妙的cache为了得到可接受的性能。 为了减少syscal代理的性能影响并且不修改当前的应用程序, exceptionless/asynchronous syscalls 这个例子已经证明, 一半的系统调用接口,用户态的进程请求一次syscall会发送一个特定的软终端指令来执行上下文切换。 这个系统调用的参数保存在通用寄存器。 无一例外syscal模型请求修改libc和kenerl: 当一个syscall请求过来, libc的位置也就是syscall参数在一个特定的页(“syscall page”) 然后切换为其他用户线程。操作系统内核,在这个空闲时间,可寻找每个程序的syscall page,然后执行syscall,然后返回后结果,然后设置完整标志在这个syscall page。 这个导致很小的内容切换,而且会直接平摊上下文切换的消耗时间。 kernel程序和用户程序在没有中断下运行更久, 这也减少cache的逐出。 这种去耦合的控制意味着我们可以甚至分配一个cpu给应用程序还有一个来服务系统调用。 这个第一个cpu依然表刘在用户态,第二个cpu保留在内核态,代替中断发生后用户态和内核态的上下文切换,他们只要通过syscall pages标志通信就可以了。
1 0
原创粉丝点击