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来提醒错误的存在。
- 将通知的频率限制在合理的范围内(也许不超过一分钟一次)。
- 抑制任何与上次发送的信息相同的信息。新的信息将只是覆盖上一个信息。
如果您有其他建议,请发表您的意见,让其他人看到。