Message Passing

来自osdev
跳到导航 跳到搜索

如果你考虑写一个 微内核,你需要布局如何管理消息传递。 此页面收集了有关如何执行此操作的注意事项。

可靠vs尽力而为

可靠
除非收件人不存在,否则保证会传递消息。 并且失败时,会通知发件人。 为了提供可靠性,消息传递系统确保消息在传输和接收过程中没有被更改或损坏。 乱序消息块被重新排序,重复的消息块被删除。 如果发生错误,系统将尝试自动重新传输消息。 消息的传输时间往往是可预测的。 但是,可靠的消息传递通常会带来明显的开销。
尽力而为
消息也许能也许不能传递给收件人。 就算消息 “被” 传递,也可能是在一段不定延迟之后。 消息可能会损坏、故障或重复。 此外,发件人可能不会收到任何成功交付的确认。 这样的消息传递听起来可能完全没用,但是尽力而为的交付通常比可靠的交付更容易实现,并且开销更低。 通过在尽力而为的传递协议之上实现可靠的消息传递协议,可以实现消息的可靠传递 (非常像带有[尽力而为]IP数据包上的[可靠]TCP协议 )。 这样的协议可能会利用 “ACK” 消息和超时来支持可靠的消息。

当数据 “必须” 逐位正确传递时 (如在传输文件时),使用可靠传递。 当大量数据必须以较低的处理开销发送时,或者当可以有几条消息被损坏或丢失 (如定期 “我还活着” 消息或流音频/视频) 时,使用尽力而为的交付。

同步vs异步

同步
进程A将消息直接传递给进程B。 如果进程B在发送时尚未准备好接收,则进程A将暂停并在进程B的 “发送” 队列上排队,直到进程B接收为止。 使用这种方法,你不需要关心消息队列-但你需要为进程排队。 请注意,如果进程B正在等待接收来自进程A的消息,而该消息未能被传递 (例如,由于错误或消息传递系统中的某些故障),则进程B将无限期地阻塞。
异步
进程A将消息发送到进程B。 消息被复制到内核空间中的专用区域,并附加到进程B的消息队列 (让我们称之为Post帧)。在下轮运行中,进程B会查看其邮箱,它将检索到该消息。 你可以用进程块用于接收消息,或者只是通过漫步检查是否有要获取的内容。 可以调用此方法 “存储和转发消息传递”。 异步消息传递的主要好处是,它允许单个线程/进程同时等待许多不相关的 “请求” 的结果。 但是,任何错误的 (或恶意的) 进程都可以快速地向其他进程重复发送垃圾消息,从而在拒绝服务攻击中占用系统资源。

反观在同步方法中,我们可能会注意到,A保证B在传递呼叫终止时收到消息,这使得它和本地RPC特别相似。 应该注意的是,如果没有此保证,实现标准C库函数可能非常困难。

围绕以下问题绞尽脑汁并不是一个坏主意: 假如进程A也期待来自进程C的消息会怎样? 它需要一种将其传达给消息路由子系统的可能性。 如果进程B向进程A发送消息,则不应唤醒进程A,因为它还希望从进程C中获得某些东西。 进程C向进程A发送消息。 然后,只有到那时,消息路由子系统才会唤醒进程A。

你需要什么原语才能使同步消息传递运行? 两个原语: request(message) 和 respond(message)。

你需要什么原语才能使异步消息传递运行? 两个原语: send(message) 和 receive(message)。

你需要什么原语才能使异步和同步消息传递运行? 三个原语: send(message), receive(message) 和 request(message), 这里的 send(message) 原语 可以或者就和 respond(message)原语一样.

可以通过异步消息传递原语获得同步消息传递,反之亦然。 因为可以增加消息转发器以及通过确认消息和消息协议使这成为可能。 不幸的是,这样做效率不高。

“Port端口” 抽象

许多微内核使用端口的概念,端口是 “接收消息的点” 或 “单向消息通信通道”。 端口设计的出发点是,你不再向线程发送消息,而是向端口 (链接到唯一线程) 发送消息。

端口可以由服务器随意分配,并且可能会限制谁可以发送和谁不能发送。 使用端口,上面的 “A侦听C,B发送到A” 问题可以通过创建一个新的端口p来解决,该端口a将仅向C开放 (并向C发送消息以告知p的端口号)。 A现在可以通过仅在p上接收,来等待C的消息。 而如果B试图在A的端口q上发送消息不会干扰。

为了解决服务器期望从不同端口接收消息 (并且使用同步消息) 的情况,我们需要使用服务器上一个类似select的功能接口,该接口从给定端口集中分配新的p端口以允许接收消息。

邮箱 Mailboxes

在某些情况下,一个线程会希望一次向多个线程广播相同的消息,或者一组生产者线程必须与另一组消费者线程进行通信。 在这种情况下,邮箱可以为多个接收者排队消息。 邮箱类似于端口,但不仅一个收件人可以检索消息,多个收件人可能会同时检索消息。 邮箱不是由单个线程拥有的,而是由接收线程之间共享的操作系统提供的公共资源。 接收消息的顺序可以是 “先进先出” (FIFO) 或基于消息优先级。

可变或固定消息大小

消息通常包括发射线程 (或回复端口) 的ID,消息代码和一些参数。 如果消息大小固定,则可以大大简化消息排队和分派代码。

当需要长于固定大小的消息时,将需要提供一种在小结构中描述长消息的方法。 来回发送4字消息并不意味着过多的处理成本,而发送到磁盘服务器的1MB数据则大不相同。 在这种情况下,建议使用分页的做法,以便将真实数据从发射器映射到接收器的地址空间。

另见

文章

论坛主题

外部链接