微内核
越大的系统潜在的bug就越多。所以微内核在降低bug方面非常有优势,seL4是世界上最小的内核之中的一个。可是seL4的性能能够与当今性能最好的微内核相比。
作为微内核,seL4为应用程序提供少量的服务。如创建和管理虚拟内存地址空间的抽象,线程和进程间通信IPC。这么少的服务靠8700行C代码搞定。seL4是高性能的L4微内核家族的新产物,它具有操作系统所必需的服务。如线程,IPC,虚拟内存,中断等。
形式验证
除了微内核。seL4还有一大特色是全然的形式验证。
seL4的实现总是严格满足上一抽象层内核行为的规约,它在不论什么情况下都不会崩溃以及运行不安全的操作,甚至能够精确的判断出seL4 在全部情况下的行为,这是了不起的。
研究发现经常使用的攻击方法对seL4无效,如恶意程序经常採用的缓存溢出漏洞。
使用面向过程语言Haskell实现了一个内核原型,用它来參与形式验证,最后依据它,用C语言又一次实现内核,作为终于内核。 顺便提一句。seL4有两仅仅team。kernel team和verification team,而连接这两个team的是 Haskell prototype。
在用C开发内核的过程中,seL4对使用C进行了例如以下限制:
1. 栈变量不得取引用,必要时以全局变量取代
2. 禁止函数指针
3. 不支持union
对seL4的formal verification(形式验证)分为两步:abstract specification(抽象规范)和executable specification(可运行规范)之间。executable specification和implementation(实现)之间。
有两个广泛的方法来进行formal verification: model checking(全自己主动)和交互式数学证明(interactive mathematical proof )。后者须要手工操作。
seL4验证使用的形式数学证明来自Isabelle/HOL,属于后者。
详细来说seL4的形式验证步骤:
1. 写出IPC、syscall、调度等全部微内核对象(kernel object)的abstract specification(in Isabelle)
2. 写出如上对象的executable specification(in Haskell)。并证明其正确实现了第一步的abstract specification。利用状态机的原理,abstract specification的每一步状态转换。executable specification都产生唯一相应的状态转换。
3. 写C实现。
通过一个SML写的C-Isabelle转换器,和Haskabelle联合形式证明C代码和第二步的Haskell定义语义一致。
seL4的实现被证明是bug-free(没有bug)的。比方不会出现缓冲区溢出,空指针异常等。还有一点就是,C代码要转换成能直接在硬件上运行的二进制代码。seL4能够确保这个转换过程不出现错误,可靠。seL4是世界上第一个(到眼下也是唯一一个)从非常强程度上被证明是安全的OS。
seL4 is the first (and still only) protected-mode OS kernel with a sound and complete timeliness analysis. Among others this means that it has provable upper bounds on interrupt latencies (as well as latencies of any other kernel operations). It is therefore the only kernel with memory protection that can give you hard real-time guarantees. 从这段英文能够看出,seL4的硬实时性非常强。
实际上OS的verification(验证)早在40年前就開始了,而seL4是振奋人心的,一是它拥有非常强的属性(properties):功能正确性(functional correctness),完整性(integrity)和机密性(confidentiality)。二是这些属性已经被形式验证到代码级别,先是C,如今又到了二进制。
相比于之前人们对于OS的验证,seL4做得更彻底,但正是借助前人的工作,seL4才干如此优秀。
内核细节
seL4的API调用分两步:第一,checking,验证參数,然后确定是否授权运行这个调用; 第二,execute,运行调用。永不失败。
The combined checking phases of all kernel calls are a substantial fraction of the kernel. 看来对内核调用的检查是非常重要的部分。
接下来来了解一下kernel objects:
- CNodes 用于存放capabilities,给线程权限去调用某个对象上的方法
- Thread Control Blocks 表示线程的运行
- IPC Endpoints 促进线程间的通信
- Virtual Address Space Objects 为一个或多个线程创建虚拟地址空间
- Interrupt Objects 让应用程序能够接收和确认来自硬件设备的中断
- Untyped Memory 它是seL4内存分配的基石
我们去了解一个OS,它的内存管理是不可缺少的。
内存分配模块能够被单独验证。在又一次使用一块内存之前。全部对这个内存的引用必须要无效。
seL4不动态为内核对象分配内存。内核对象要由应用程序控制的内存区域通过Untyped Memory来创建。这样能够精确控制应用程序使用的物理内存。并且能够做到程序与程序之间物理内存的isolation。
seL4是一个单内核栈的操作系统。在启动时期,seL4会预先为内核须要的内存如代码区,数据区和栈分配内存。
seL4实现了一个capability-based的訪问控制模型。每个用户空间的线程有一个相关联的capability space (CSpace),这个空间包括了这个线程处理的capabilities,也就是说它管理着这个线程訪问的资源。
CNode有一些slot,每个slot须要16字节的物理内存,它能够恰恰保存一个capability。同其它对象一样,CNode必须要通过seL4 Untyped Retype()在合适数量的untyped memory上来创建。
seL4用TCB(thread control block)描写叙述一个线程,每个TCB对一个CSpace和VSpace(它们可与其它线程共享)。一个TCB一般有一个IPC buffer。
seL4提供了消息传递机制用于线程间的通信。
seL4採用256个优先级的抢占式轮转调度机制,当一个线程创建或改动了还有一个线程,它仅仅能将还有一线程的优先级设为比它低或跟它一样。线程优先级用函数seL4 TCB Configure() 和 seL4 TCB SetPriority() 来设置。