跳转至主要内容

OpenVOS操作系统提供了一个高级应用编程接口(API),总体上使系统编程变得简单。 但有时,它变得容易--因为对s$...例程的一个简单的子程序调用可能隐藏了很多复杂的东西。

这是一个不定期的系列文章中的第一篇,目的是提醒您注意这些陷阱,以便在您的应用设计中避免它们。

第25行信息的弊端

能够在终端的第25行(或者不管是最底层的)写一条消息,让用户(或者正在运行的程序)通知其他用户异常情况。 命令行接口是send_message命令。 命令和用户程序最终会调用s$send_message API子程序。 这个调用的参数提供了接收者的user_name,该用户可能登录的目标模块_name,通知文本,以及一些用于修改操作方面的标志。 有权限的调用者可以指定发送者的名字,否则默认为发送进程的用户名。

目前看来很简单。 由于该操作需要访问另一个用户所拥有的终端,内核将请求发送到目标模块上的TheOverseer进程的服务器队列上。 通常情况下,发送进程会等待消息发送的状态,但也可以选择不等待这个回复。

任何模块的Overseer进程都会跟踪所有的登录进程和这些进程使用的终端设备。 当它收到发送消息的请求时,它会搜索它的进程和设备列表,对于每个与receiver_name参数相匹配的进程user_name,它将一个端口附加到该进程的终端设备上,打开该端口,将消息写入通知行,关闭该端口,并分离该端口。 如果有多个进程与receiver_name参数相匹配,则对每个进程重复进行附加/打开/写入/关闭/分离的循环。

好吧--这比我们最初讨论的要复杂一些。 进一步探索,我们发现系统中的任何给定模块都可能托管登录进程,而真正的终端是另一个系统/模块上的设备,该设备使用Open StrataLink (OSL)通过网络登录(使用login -module命令)。 现在,在该终端上看似简单的附加/打开/写入/关闭/分离操作,却要涉及到OSL进程和对远程模块的网络远程过程调用,而且比模块上的处理成本要高得多。

当接收方user_name被指定为starname时,效果就会放大,因为这个starname可能与多个或所有登录用户相匹配。 如果目标模块也被指定为starname,效果会进一步放大。 最坏的情况是将消息发送给用户"*.*"(所有用户,所有组)的模块"*"(当前系统的所有模块)。

执行情况

s$expand_module_starname(target_module) =>  module_list;

foreach module_name in module_list
   send_overseer_request(module_name, send_message_request_data)
   The message is sent via a server queue and OSL to TheOverseer process
   on that module.

   TheOverseer  process on each receiving module then does:
   foreach terminal_process in TheOverseer’s list of
      login processes and sub-processes;

      if (terminal_process user_name matches receiver star name)
         if (messages_queued_for_device < 5)
            queue it for the login device
         else
            reject the request (e$too_many_terminal_messages)
   同时,一次最多使用10个端口发送任何排队的
        终端的消息。
   对于每个终端的每个信息
      连接端口
      开放端口
      s$control(...WRITE_SYSTEM_MESSAGE...)
      关闭港口
      拆卸口

这个处理是在每个终端的no_wait_mode下进行的,所以
延迟(如跨网络的I/O请求)只影响了
该终端的消息处理。   

如果任何信息在300秒内无法送达,则会被刷新。

当应用程序使用这种机制报告错误时,大量的错误涌来,应用程序很容易陷入报告的泥潭,在等待其他消息处理和淹没用户终端的消息之间交替进行,这些消息到达的速度太快,无法理解。

撤销

现在你知道了幕后的情况,我可以给你的指导是。

  • 仔细制作用户名和模块名称的星号,以确保你只接触到必须收到消息的用户,而没有其他用户。 例如,John_Doe.*或*.Operations或John_Doe.SysAdmin。
  • 考虑实现非starname用户列表,分别通知和发送每个通知。
  • 将错误信息的细节放在其他地方(例如,错误日志),并使用s$send_message来提醒错误的存在。
  • 将通知的频率限制在合理的范围内(也许不超过一分钟一次)。
  • 抑制任何与上次发送的信息相同的信息。新的信息将只是覆盖上一个信息。

如果您有其他建议,请发表您的意见,让其他人看到。

© 2024Stratus Technologies.