본문 바로가기

OpenVOS 운영체제는 전반적으로 시스템 프로그래밍을 용이하게 하는 고수준 응용 프로그램 인터페이스(API)를 제공합니다. 그러나 때로는 너무 쉬워질 수 있습니다. s$… 루틴에 대한 단순한 서브루틴 호출이 많은 복잡성을 숨길 수 있기 때문입니다.

이것은 애플리케이션 설계 시 이러한 함정을 피할 수 있도록 여러분의 주의를 환기시키기 위한 불규칙적인 연재 글의 첫 번째 글입니다.

25줄 메시지의 폐해

터미널의25번째 (또는 맨 아래) 줄에 메시지를 작성하는 기능은 사용자(또는 실행 중인 프로그램)가 비정상적인 상황을 다른 사용자에게 알릴 수 있게 합니다. 명령줄 인터페이스는 send_message 명령어입니다. 명령어 및 사용자 프로그램은 궁극적으로 s$send_message API 서브루틴을 호출합니다.    이 호출의 인수는 수신자의 사용자 이름, 해당 사용자가 로그인되어 있을 수 있는 대상 모듈 이름, 알림 텍스트, 그리고 작업의 측면을 수정하는 몇 가지 플래그를 제공합니다. 특권 호출자는 발신자의 이름을 지정할 수 있으며, 그렇지 않으면 발신 프로세스의 사용자 이름이 기본값으로 사용됩니다.

지금까지는 간단해 보입니다. 해당 작업이 다른 사용자가 소유한 터미널에 대한 접근을 필요로 하기 때문에, 커널은 대상 모듈의 TheOverseer 프로세스를 위한 서버 큐에 요청을 전송합니다. 일반적으로, 전송 프로세스는 메시지 전달 상태를 기다리지만, 이 응답을 기다리지 않기로 선택할 수도 있습니다.

모든 모듈의 TheOverseer 프로세스는 모든 로그인 프로세스와 해당 프로세스가 사용하는 터미널 장치를 추적합니다.   메시지 전송 요청을 수신하면, 프로세스 및 장치 목록을 검색하고, receiver_name 인수와 일치하는 user_name을 가진 각 프로세스에 대해 해당 프로세스의 터미널 장치에 포트를 연결(attach)하고, 포트를 열고, 메시지를 알림 라인에 기록(write)한 후, 포트를 닫고(close) 연결을 해제(detach)합니다. receiver_name 인수와 일치하는 프로세스가 여러 개인 경우, 이 연결/열기/기록/닫기/해제 순환이 각 프로세스에 대해 반복됩니다.

좋아요 – 이건 우리가 처음 논의했던 것보다 조금 더 복잡합니다. 더 자세히 살펴보면, 시스템 내 특정 모듈은 실제 터미널이 다른 시스템/모듈에 있는 장치인 로그인 프로세스를 호스팅할 수 있으며, 해당 장치는 네트워크를 통해 로그인하기 위해 Open StrataLink(OSL)을 사용했습니다(login –module 명령어 사용).   이제 해당 터미널에 대한 단순해 보이는 연결/열기/쓰기/닫기/분리 작업은 OSL 프로세스와 원격 모듈에 대한 네트워크 원격 프로시저 호출을 포함해야 하며, 이는 모듈 내 처리보다 훨씬 더 많은 비용이 듭니다.

수신자 user_name이 여러 로그인 사용자 또는 모든 사용자와 일치할 수 있는 별표 이름으로 지정될 경우 효과가 증폭됩니다. 또한 대상 모듈도 별표 이름으로 지정되면 효과가 더욱 증폭됩니다. 최악의 경우는 모듈 "*"(현재 시스템의 모든 모듈)에 사용자 "*.*"(모든 사용자, 모든 그룹)에게 메시지를 전송하는 경우입니다.

구현

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과 같은 형식을 사용하십시오.
  • 별명 없는 사용자 목록을 구현하여 각 알림을 개별적으로 전송하는 방안을 고려하십시오.
  • 오류 메시지의 세부 내용은 다른 곳(예: 오류 로그)에 기록하고, s$send_message를 사용하여 오직 오류 발생 여부만 알리도록 하십시오.
  • 알림 빈도를 합리적인 수준으로 제한하십시오(예: 1분에 한 번 이하).
  • 마지막으로 전송된 메시지와 동일한 메시지는 모두 억제합니다. 새 메시지는 이전 메시지를 덮어쓰게 됩니다.

다른 제안이 있으시면 다른 분들이 볼 수 있도록 댓글을 남겨주세요.

© 2024 Stratus Technologies.