微核进程间通信

2021/5/10 7:29:01

本文主要是介绍微核进程间通信,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

微核进程间通信

  • 前言
  • 一、IPC设计
    • 1. L4消息传递:数据传输性能
    • 2. L4控制流转移:控制流切换性能
    • 3. L4权限检查:capability
  • 二、LRPC迁移线程模型
    • 1. 允许被调用者运行在调用者的上下文中
    • 2. LRPC 同步的进程间通信设计
  • 总结
  • 参考


前言

微内核所做的是将原本运行在内核态的一些功能剥离出来,单独以系统服务的形式运行在用户态,比如内存管理,文件系统等。很多系统调用最终由系统服务处理,因而进程间通信性能是评价系统性能的重要指标。

一、IPC设计

几种通信设计

  • Mach 端口-消息,端口隔开进程其本质是个消息队列,采用发送监听机制,发送的消息中承载了接收者如何建立下一级端口。(建立通信连接:通过进程间通信来传递端口的思想被后来的大部分微内核继承)
  • L4 围绕进程间通信设计的微内核,内核只保留了基本功能,包含地址空间、线程、进程间通信等,尽量减少内核代码。

就L4系列的详细叙述

1. L4消息传递:数据传输性能

以减少数据拷贝为目的,L4按消息长度将消息分为长消息、短消息等;以消息传递某些信息,seL4以消息传递Capability。

  • 短消息使用寄存器传参,实现零拷贝。

发送进程将参数放置在寄存器中,进入内核态时,内核从发送者的上下文切换到接收者的上下文,但保留存放在寄存器中的参数。缺点是收到硬件的寄存器数量限制,可用寄存器数量也受系统调用ABI数量的影响。

  • 长消息通过内核辅助完成传递: 一般情况为两次拷贝,发送者用户态到内核态缓冲区,内核态缓冲区到接收者用户态

一次拷贝的优化:每个进程在其内核地址空间预留一段区域作为临时缓冲区,进程间并不共享内核段的临时缓冲区。如果将发送者进程的内核缓冲区的虚拟空间映射到接收者进程的用户态物理内存区域。拷贝一次就直接保存到了接收者进程。

避免上下文切换:消息传输接口层面,长消息可以在单词调用中指定多个缓冲区。引入的问题:拷贝本身在内核态,缺页异常时(发送者接收者都可能缺页)的页管理程序又在用户态,用户态页处理完成后内核需要重新建立原始的系统调用上下文。

一个演进方向是通信进程双方建立共享内存区,进程自己负责传输大量数据,避免内核参与。

2. L4控制流转移:控制流切换性能

调度的不确定性会影响IPC的时延

惰性调度:只刷新TCB中线程的状态,而不把线程从调度队列移除。
直接进程切换:将调度程序从控制流转移的关键路径中移除,直接完成从调用者到被调用者的切换。

3. L4权限检查:capability

直接通信场景,接收者进程负责检查请求者的权限很有可能会受到拒绝服务攻击DDOS。大多采用间接通信场景,该场景下,微内核组件可以使用capability权限机制解决鉴权问题。其中,capability时对内核对象(对内核的一切管理结构如IPC,TCB等的抽象)的索引+权限。

微内核在内核中为每个通信连接维护一个IPC内核对象,包括接收者,发送者,缓冲区等等信息。
当发送者进程要通信时,需要告诉内核一个特定的capability从而发起通信,内核检测capability的正确性及其权限,通过capability找到接收者。
这意味着:两个进程通信前,需要通过命名服务等方式获取到对应的capability。

二、LRPC迁移线程模型

Lightweight Remote Procedure Call 轻量级远程过程调用

  • 简化控制流切换,客户端线程执行服务端代码
  • 简化数据传输,共享参数栈和寄存器
  • 简化接口,减少序列化开销
  • 优化并发,避免共享的全局数据结构

1. 允许被调用者运行在调用者的上下文中

内核不阻塞调用者线程,让调用者执行被调用者代码,整个过程被调用者线程不涉及被唤醒,被调用者像代码的提供者。
内核不会完整的切换进程的上下文,只切换进程的地址空间以及系统的状态。这样就不会涉及线程切换、优先级切换,不用调度器参与,减少了内核调度的时间开销,简化了内核的IPC处理。

2. LRPC 同步的进程间通信设计

[参数栈与寄存器] 内核为每一个LRPC分配好一个参数栈,同时映射到客户端进程和服务端进程的地址空间,在通信时客户端进程只需要将参数准备到参数栈即可,不需要内核做拷贝。整个过程与函数调用的参数准备相似,与L4的短消息类似,通信时不会切换通用寄存器,直接使用当前的通用寄存器。可见,寄存器+参数栈一起构成了,LRPC通信时的数据传递(寄存器不足时由参数栈补充)。

[通信连接的建立过程] 当client申请与server侧建立连接时,内核会分配参数栈和连接记录,并返回给客户端一个绑定对象,之后客户端通过该绑定对象发起通信。
其中,连接记录类似于函数的返回地址,当服务端执行完需要返回时,内核从连接记录中获取返回信息。

总结

以上内容多参考《现代操作系统:原理与实现》,仅供个人学习使用。

参考

陈海波老师《现代操作系统:原理与实现》 机械工业出版社



这篇关于微核进程间通信的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程