Flexible System Call Scheduling with Exception-Less System Calls
1. 摘要
本篇论文主要介绍的一种新型 系统调用
思路。
传统系统调用主要是通过内核提供入口,用户态调用时通过特殊的机器指令和相应的寄存器进入内核执行相关的函数调用。而本篇论文提出的新型系统调用主要是一种依赖于共享内存
、后台内核线程技术
的函数调用,这种函数调用不需要用户态陷入内核,而这样子做的好处主要是能够提高用户态代码的locality
本篇论文的首先会评测分析传统系统调用在 system intensive workloads 下对性能的严重影响;在基于这种现象的观察基础上,作者提出了新型系统调用,并对其设计实现进行了阐述;最后作者在 Apache、MySQL上应用了新型系统调用,来评测分析这种修改对性能的提升效果。
2. 设计实现
2.1 传统系统调用及性能问题
传统系统调用是用户态用来和 kernel 通信的主要方式,依赖于同步的调用模型,在系统调用完成之前,应用程序无法进行用户态的执行。
传统系统调用的问题主要是,在一些系统调用密集的工作负载下,从用户态切换刀内核态执行,将会破坏应用态的 locality
,对 locality
的破坏将会严重的影响应用程序的性能。
2.2 exception-less system call
显然,传统系统调用的问题主要就是对 locality 的破坏,导致硬件的利用率差,而 locality
的破坏主要是由于用户态和内核态的切换导致的,即主要是由于 exception-based execution mode l造成的。
本文提出了一种 exception-less system call。用户态和内核态之间共享一个 syscall page,用户态将系统调用的请求写入这个共享内存,内核态的特殊线程(syscall threads)负责处理这个共享内存的所有请求。
2.2.1 设计
exception-less system call 的设计包含两方面
- 提供给用户态线程一个注册 system calls 的接口
- 提供一个异步的内核态线程系统,负责处理 system calls
2.2.1.1 用户态接口
syscall page
syscall page 是内核态和用户态之间共享的内存,主要用来存放 系统调用 entry。用户态应用程序在需要系统调用时,需要在这段内存中寻找一个空闲的 entry,然后填入相应的字段。
syscall entry 包含的字段主要有:syscall number、arguments、status [free / submitted / busy / done]、result
syscall number number of arguments status arg1 … arg6 return value 4Byte 2Byte 2Byte 8Byte … 8Byte 8Byte
2.2.1.2 内核态异步执行线程
exception-less system call 不会主动通知内核有系统调用请求,因此内核态需要一种机制来异步处理这种请求,这种在内核态下专门处理系统调用请求的线程被称作 syscall thread。
syscall threads 只有在用户态线程无法继续执行的时候才会被唤醒,然后执行请求。
syscall threads 可以被调度在和用户态线程不同的 core 上,以此来提高用户态线程的 locality。
2.2.2 实现
在 exception-less syscall 的实现中还需要2个使用 传统系统调用 方式的系统调用接口:flex_register 和 flex_wait,这两个系统调用接口主要是作为扩展,用来启用 FlexSC(即本文实现的exception-less syscall) 的接口
2.2.2.1 flex_register
flex_register 主要是用户态用来启用 FlexSC 的接口,当用户态的进程需要使用 FlexSC 时,应当在 process 创建时,调用这个系统调用。
flex_register 的执行逻辑主要包含2部分
- 在内核态映射 syscall pages 到用户态
- 为每一个syscall entry创建一个syscall threads
2.2.2.2 flex_wait
flex_wait 也是一个传统系统调用,用来在用户态线程无法继续执行的情况下,主动通知内核唤醒 syscall threads 处理系统调用请求。当有至少一个 syscall 完成,就可以唤醒用户态由于无法继续执行而进入等待的线程。