Специфікація BTRON3 (Український переклад) | Специфікація ОС Sakamura BTRON / BTRON3
Повернутися до змісту цього розділу
Попередня сторінка: 1.1 Управління процесами та задачами (Повернутися)
Наступна сторінка: 1.3 Синхронізація та комунікація задач (Перейти)

1.2 Система міжпроцесних повідомлень (Message Passing)

1.2.1 Огляд міжпроцесних повідомлень (Overview)

Кожен процес має власну чергу повідомлень (Message Queue), через яку здійснюється міжпроцесний обмін повідомленнями. Ця функціональність використовується не лише для передачі повідомлень прикладних програм між процесами, а й для системних сповіщень ядра (наприклад, повідомлень про завершення дочірніх процесів та сповіщень таймера). З цієї причини формати окремих типів повідомлень регламентуються системою.

Повідомлення надсилається у чергу повідомлень цільового процесу, а адресат вказується за допомогою його ідентифікатора процесу PID. Також процес-відправник однозначно ідентифікується за власним PID.

Кожне повідомлення має наведену нижче структуру і поділяється на 31 тип за полем msg_type (значення 1–31). Завдяки побітовій масці типів (Type Mask) під час прийому або очищення повідомлень можна вибірково вказувати один або кілька типів повідомлень одночасно.

typedef union {
    struct {
        W pid;
        W code;
    } ABORT;        /* Повідомлення про аварійне завершення процесу (MS_ABORT) */
    struct {
        W pid;
        W code;
    } EXIT;         /* Повідомлення про нормальне завершення процесу (MS_EXIT) */
    struct {
        W pid;
        W code;
    } TERM;         /* Повідомлення про примусове завершення процесу (MS_TERM) */
    struct {
        W code;
    } TMOUT;        /* Повідомлення про спливання таймауту (MS_TMOUT) */
    struct {
        W code;
    } SYSEVT;       /* Повідомлення про системні події (MS_SYS1..MS_SYS31) */
    struct {
        UB msg_str[32];
    } ANYMSG;       /* Загальні повідомлення додатків (MS_USER) */
} MSGBODY;

typedef struct message {
    W msg_type;     /* Тип повідомлення (1..31) */
    W msg_size;     /* Розмір тіла повідомлення (байти) */
    MSGBODY msg_body; /* Буфер тіла повідомлення */
} MESSAGE;

У чергу повідомлень процесу можуть надходити як повідомлення від інших процесів, так і повідомлення від власного процесу (якщо цільовим адресатом вказано власний процес), а також системні повідомлення про спливання таймауту (MS_TMOUT). Крім того, повідомлення про завершення дочірніх процесів (MS_ABORT, MS_EXIT, MS_TERM) також надходять у цю чергу.

Черга повідомлень працює за принципом FIFO — повідомлення записуються суворо у порядку надсилання. Якщо під час відправлення черга отримувача заповнена, відправник може заблокуватися до появи вільного місця або негайно повернути код помилки.

Зазвичай прийняті повідомлення накопичуються у черзі і вилучаються за запитом прийому повідомлення, проте за допомогою реєстрації обробника повідомлень (Message Handler) при надходженні повідомлення вказаного типу можна виконувати асинхронну обробку. Це застосовується як системне переривання.

1.2.2 Класифікація та типи системних повідомлень

Повідомлення поділяються на 31 тип за їхніми номерами 1–31: з них типи 1–5 зарезервовані ядром системного призначення, типи 6–23 зарезервовані підсистемами ядра та графічною оболонкою (Shell Manager), а типи 24–31 надаються для вільного використання прикладними програмами.

Типи повідомлень визначаються наступним чином:

#define MS_ABORT    ( 1)    /* Аварійне завершення процесу */
#define MS_EXIT     ( 2)    /* Нормальне завершення процесу */
#define MS_TERM     ( 3)    /* Примусове завершення процесу */
#define MS_TMOUT    ( 4)    /* Спливання таймауту */
#define MS_SYSEVT   ( 5)    /* Критична системна подія */

#define MS_SYS1     ( 6)    /* Системне резервування ядра */
#define MS_SYS2     ( 7)    /* Системне резервування ядра */
#define MS_SYS3     ( 8)    /* Системне резервування ядра */
#define MS_SYS4     ( 9)    /* Системне резервування ядра */
#define MS_SYS5     (10)    /* Системне резервування ядра */
#define MS_MNG0     (11)    /* Резервування оболонки Shell */
#define MS_MNG1     (12)    /* Резервування оболонки Shell */
#define MS_MNG2     (13)    /* Резервування оболонки Shell */
#define MS_MNG3     (14)    /* Резервування оболонки Shell */
#define MS_MNG4     (15)    /* Резервування оболонки Shell */
#define MS_MNG5     (16)    /* Резервування оболонки Shell */
#define MS_MNG6     (17)    /* Резервування оболонки Shell */
#define MS_MNG7     (18)    /* Резервування оболонки Shell */
#define MS_MNG8     (19)    /* Резервування оболонки Shell */
#define MS_MNG9     (20)    /* Резервування оболонки Shell */
#define MS_MNG10    (21)    /* Резервування оболонки Shell */
#define MS_MNG11    (22)    /* Резервування оболонки Shell */
#define MS_MNG12    (23)    /* Резервування оболонки Shell */

#define MS_TYPE0    (24)    /* Повідомлення прикладних додатків */
#define MS_TYPE1    (25)
#define MS_TYPE2    (26)
#define MS_TYPE3    (27)
#define MS_TYPE4    (28)
#define MS_TYPE5    (29)
#define MS_TYPE6    (30)
#define MS_TYPE7    (31)

#define MS_MIN      ( 1)    /* Мінімальний номер типу повідомлення */
#define MS_MAX      (31)    /* Максимальний номер типу повідомлення */

Кожному типу повідомлення відповідає бітовий прапор у масці типів (Type Mask), і завдяки побітовій комбінації (OR) масок можна вказувати кілька типів повідомлень одночасно.

Маски типів повідомлень визначаються наступним чином:

#define MSGMASK(msgtype)    (1 << ((msgtype) - 1))

#define MM_ABORT    MSGMASK(MS_ABORT)   /* Аварійне завершення процесу */
#define MM_EXIT     MSGMASK(MS_EXIT)    /* Нормальне завершення процесу */
#define MM_TERM     MSGMASK(MS_TERM)    /* Примусове завершення процесу */
#define MM_TMOUT    MSGMASK(MS_TMOUT)   /* Спливання таймауту */
#define MM_SYSEVT   MSGMASK(MS_SYSEVT)  /* Критична системна подія */
#define MM_SYS1     MSGMASK(MS_SYS1)    /* Системне резервування ядра */
#define MM_SYS2     MSGMASK(MS_SYS2)    /* Системне резервування ядра */
#define MM_SYS3     MSGMASK(MS_SYS3)    /* Системне резервування ядра */
#define MM_SYS4     MSGMASK(MS_SYS4)    /* Системне резервування ядра */
#define MM_SYS5     MSGMASK(MS_SYS5)    /* Системне резервування ядра */
#define MM_MNG0     MSGMASK(MS_MNG0)    /* Резервування оболонки Shell */
#define MM_MNG1     MSGMASK(MS_MNG1)    /* Резервування оболонки Shell */
#define MM_MNG2     MSGMASK(MS_MNG2)    /* Резервування оболонки Shell */
#define MM_MNG3     MSGMASK(MS_MNG3)    /* Резервування оболонки Shell */
#define MM_MNG4     MSGMASK(MS_MNG4)    /* Резервування оболонки Shell */
#define MM_MNG5     MSGMASK(MS_MNG5)    /* Резервування оболонки Shell */
#define MM_MNG6     MSGMASK(MS_MNG6)    /* Резервування оболонки Shell */
#define MM_MNG7     MSGMASK(MS_MNG7)    /* Резервування оболонки Shell */
#define MM_MNG8     MSGMASK(MS_MNG8)    /* Резервування оболонки Shell */
#define MM_MNG9     MSGMASK(MS_MNG9)    /* Резервування оболонки Shell */
#define MM_MNG10    MSGMASK(MS_MNG10)   /* Резервування оболонки Shell */
#define MM_MNG11    MSGMASK(MS_MNG11)   /* Резервування оболонки Shell */
#define MM_MNG12    MSGMASK(MS_MNG12)   /* Резервування оболонки Shell */

#define MM_TYPE0    MSGMASK(MS_TYPE0)   /* Повідомлення прикладних додатків */
#define MM_TYPE1    MSGMASK(MS_TYPE1)
#define MM_TYPE2    MSGMASK(MS_TYPE2)
#define MM_TYPE3    MSGMASK(MS_TYPE3)
#define MM_TYPE4    MSGMASK(MS_TYPE4)
#define MM_TYPE5    MSGMASK(MS_TYPE5)
#define MM_TYPE6    MSGMASK(MS_TYPE6)
#define MM_TYPE7    MSGMASK(MS_TYPE7)

#define MM_ALL      (0x7fffffff)        /* Маска всіх типів повідомлень */
#define MM_NULL     (0)                 /* Порожня маска */

Системні повідомлення автоматично генеруються ядром операційної системи і мають наведений нижче вміст. Вони не відкидаються при переповненні черги і завжди гарантовано доставляються.

MS_ABORT — Повідомлення про аварійне завершення процесу:

Надсилається батьківському процесу від дочірнього процесу, якщо дочірній процес був аварійно завершений внаслідок системної помилки або спрацювання обробника MH_TERM.

  W msg_type /* Тип = MS_ABORT (1) */
  W msg_size /* Розмір тіла у байтах (8) */
  W pid      /* PID завершеного дочірнього процесу */
  W code     /* Код системної помилки (або 0 при зупинці MH_TERM) */
MS_EXIT — Повідомлення про нормальне завершення процесу:

Надсилається батьківському процесу, коли дочірній процес завершує виконання викликом ext_prc().

  W msg_type /* Тип = MS_EXIT (2) */
  W msg_size /* Розмір тіла у байтах (8) */
  W pid      /* PID завершеного дочірнього процесу */
  W code     /* Код завершення, переданий у ext_prc() */
MS_TERM — Повідомлення про примусове завершення процесу:

Надсилається батьківському процесу, коли дочірній процес примусово припиняє виконання викликом ter_prc().

  W msg_type /* Тип = MS_TERM (3) */
  W msg_size /* Розмір тіла у байтах (8) */
  W pid      /* PID припиненого дочірнього процесу */
  W code     /* Код завершення, переданий у ter_prc() */
MS_TMOUT — Повідомлення про спливання таймауту:

Надсилається власному процесу після закінчення часу, вказаного у виклику таймера req_tmg().

  W msg_type /* Тип = MS_TMOUT (4) */
  W msg_size /* Розмір тіла у байтах (4) */
  W code     /* Код користувача, переданий у req_tmg() */

1.2.3 Обробники повідомлень (Message Handlers)

За замовчуванням повідомлення у черзі очікують на явний виклик прийому rcv_msg(). Проте за допомогою реєстраційної функції def_msg() процес може визначити функцію обробника повідомлень (Message Handler) для кожного з типів повідомлень (1–31).

Правила виконання та обробки повідомлень:

Прототип функції обробника повідомлень:

VOID msg_hdr(W pid, MESSAGE *r_msg)
{
    /* pid   — PID процесу-відправника (0 якщо відправник — власний процес) */
    /* r_msg — вказівник на прийняте повідомлення */

    /* [Обробка прийнятого повідомлення] */

    ret_msg(0); /* Завершення обробника (повернення у точку переривання) */

    /* АБО */

    ret_msg(1); /* Підготовка до нелокального переходу */
    longjmp(reent, code); /* Перехід longjmp на збережений середовищний контекст */
}

Система надає 3 стандартні системні обробники за замовчуванням:

MH_NONE — Ігнорування повідомлення:

Повідомлення вилучається з черги та ігнорується без виконання будь-яких дій. Заблоковані системні виклики очікування НЕ перериваються.

MH_BREAK — Переривання очікування:

Повідомлення вилучається з черги. Наявні заблоковані виклики очікування перериваються і повертають код помилки ER_MINTR.

MH_TERM — Аварійне завершення процесу:

При надходженні повідомлення процес негайно припиняє виконання і надсилає батьківському процесу системне повідомлення MS_ABORT з кодом 0.

1.2.4 Визначення типів даних та констант (Data Types & Constants)

□ Структура системного повідомлення (MESSAGE)

typedef union {
    struct {            /* MS_ABORT */
        W pid;
        W code;
    } ABORT;
    struct {            /* MS_EXIT */
        W pid;
        W code;
    } EXIT;
    struct {            /* MS_TERM */
        W pid;
        W code;
    } TERM;
    struct {            /* MS_TMOUT */
        W code;
    } TMOUT;
    struct {            /* MS_SYSEVT */
        W code;
    } SYSEVT;
    struct {            /* Загальні повідомлення додатків (MS_USER) */
        UB msg_str[32];
    } ANYMSG;
} MSGBODY;

typedef struct message {
    W msg_type;         /* Тип повідомлення (1..31) */
    W msg_size;         /* Розмір тіла повідомлення (у байтах) */
    MSGBODY msg_body;   /* Буфер тіла повідомлення */
} MESSAGE;

#define MSGSIZE(msgsz)  (offsetof(MESSAGE, msg_body) + msgsz)

□ Режими та опції повідомлень (Message Options)

#define WAIT        0x0000  /* Очікування у разі заповнення/відсутності повідомлення */
#define NOWAIT      0x0001  /* Негайне повернення без очікування */
#define CONFM       0x0002  /* Запит підтвердження прийому від отримувача */
#define WAIEVT      0x0004  /* Очікування повідомлення або сигналу brk_msg() */
#define CLR         0x0000  /* Вилучення повідомлення з черги після прийому */
#define NOCLR       0x0008  /* Читання повідомлення без вилучення з черги */
#define CHECK       0x0010  /* Перевірка наявності повідомлення без копіювання */

□ Системні обробники за замовчуванням

#define MH_NONE     ((FUNCP)1)  /* Ігнорування повідомлень */
#define MH_BREAK    ((FUNCP)2)  /* Переривання очікування (ER_MINTR) */
#define MH_TERM     ((FUNCP)3)  /* Аварійне завершення процесу */

1.2.5 Системні виклики обміну повідомленнями (Message System Calls)

snd_msg
 
Надсилання міжпроцесного повідомлення (Send Message)

【Синтаксис / Прототип】

ERR snd_msg(W pid, MESSAGE* msg, W opt)

【Параметри】

W         pid    PID цільового процесу-отримувача
                 > 0 : Конкретний цільовий процес
                 = 0 : Власний процес
                 =-1 : Усі дочірні процеси
MESSAGE*  msg    Вказівник на структуру надсиланого повідомлення
W         opt    Режими надсилання (NOWAIT | WAIT | CONFM)
NOWAIT:

Якщо черга отримувача заповнена, виклик негайно повертає код помилки ER_NOSPC без очікування.

WAIT:

Якщо черга отримувача заповнена, процес-відправник переходить у стан очікування до появи вільного місця у черзі.

CONFM:

Запитує підтвердження прийому. Відправник блокується доти, доки отримувач не прочитає повідомлення викликом rcv_msg() у режимі CLR.

【Значення, що повертається】

= 0      Успішне виконання (E_OK)
< 0      Помилка (Код помилки)

【Детальний опис】

Надсилає повідомлення msg у чергу повідомлень процесу pid.

【Коди помилок】

ER_ADR   : Неприпустима адреса вказівника (msg) у віртуальній пам'яті.
ER_MINTR : Обробку перервано внаслідок надходження системного сигналу.
ER_NOPRC : Процес із вказаним PID не існує або вже завершений.
ER_NOSPC : Черга повідомлень отримувача заповнена (при режимі NOWAIT).
ER_PAR   : Неприпустиме значення одного з параметрів системного виклику.
ER_SELF  : Спроба надіслати повідомлення самому собі у режимі підтвердження CONFM.
ER_SZOVR : Розмір тіла повідомлення виходить за дозволені межі.
rcv_msg
 
Прийом міжпроцесного повідомлення (Receive Message)

【Синтаксис / Прототип】

WERR rcv_msg(W t_mask, MESSAGE* msg, W msgsz, W opt)

【Параметри】

W         t_mask Маска типів повідомлень для прийому (наприклад, MM_ALL)
MESSAGE*  msg    Буфер для збереження прийнятого повідомлення
W         msgsz  Розмір буфера msg у байтах (msgsz >= 8)
W         opt    Режими прийому: (WAIT | NOWAIT | WAIEVT) | (CLR | NOCLR) | (CHECK)
WAIT:

Якщо відповідне повідомлення відсутнє у черзі, процес очікує його надходження.

NOWAIT:

Якщо відповідне повідомлення відсутнє у черзі, виклик негайно повертає код помилки ER_NONE.

WAIEVT:

Чекає на повідомлення або сигнал переривання, згенерований системним викликом brk_msg().

CLR:

Після прочитання повідомлення воно вилучається з черги повідомлень (режим за замовчуванням).

NOCLR:

Повідомлення копіюється у буфер msg, але залишається у черзі повідомлень.

CHECK:

Перевіряє наявність повідомлення у черзі без копіювання його вмісту у буфер.

【Значення, що повертається】

> 0      Успішне виконання (PID процесу-відправника)
= 0      Успішне виконання (відправник відсутній або перевірка CHECK)
< 0      Помилка (Код помилки)

【Детальний опис】

Зчитує із черги повідомлення, тип якого відповідає масці t_mask, і копіює його у буфер msg.

【Коди помилок】

ER_ADR   : Неприпустима адреса вказівника (msg) у віртуальній пам'яті.
ER_MINTR : Обробку перервано внаслідок надходження системного сигналу.
ER_NONE  : Повідомлення з вказаною маскою t_mask відсутнє у черзі (при NOWAIT).
ER_PAR   : Неприпустиме значення одного з параметрів (наприклад, msgsz < 8).
ER_SZOVR : Наданий буфер msgsz занадто малий для збереження тіла даного повідомлення.
clr_msg
 
Очищення черги повідомлень (Clear Message Queue)

【Синтаксис / Прототип】

ERR clr_msg(W t_mask, W last_mask)

【Параметри】

W t_mask    Маска типів повідомлень для вилучення з черги (наприклад, MM_ALL)
W last_mask Маска типів повідомлень для вилучення тільки останніх записів

【Значення, що повертається】

>= 0     Успішне виконання (Кількість вилучених повідомлень)
< 0      Помилка (Код помилки)

【Детальний опис】

Вилучає з черги повідомлення власного процесу, тип яких збігається з маскою t_mask.

【Коди помилок】

ER_PAR   : Неприпустиме значення параметрів маски (t_mask <= 0).
req_tmg
 
Запит таймера повідомлень / таймауту (Request Message Timer)

【Синтаксис / Прототип】

ERR req_tmg(W time, W code)

【Параметри】

W time   Час затримки у мілісекундах (time > 0)
W code   Користувацький код, що буде переданий у повідомленні MS_TMOUT

【Значення, що повертається】

= 0      Успішне виконання (E_OK)
< 0      Помилка (Код помилки)

【Детальний опис】

Замовляє надсилання системного повідомлення про спливання таймауту (MS_TMOUT) із кодом code у чергу власного процесу через time мілісекунд.

【Коди помилок】

ER_NOSPC : Недостатньо системної пам'яті для реєстрації таймера.
ER_PAR   : Неприпустиме значення інтервалу часу (time <= 0).
can_tmg
 
Скасування таймера повідомлень (Cancel Message Timer)

【Синтаксис / Прототип】

ERR can_tmg(VOID)

【Параметри】

Відсутні (VOID)

【Значення, що повертається】

= 0      Успішне виконання (E_OK)

【Детальний опис】

Скасовує раніше встановлений таймер повідомлень req_tmg() для власного процесу.

【Коди помилок】

Помилок немає (завжди повертає E_OK).

def_msg
 
Реєстрація обробника повідомлень (Define Message Handler)

【Синтаксис / Прототип】

ERR def_msg(W t_mask, FP msghdr)

【Параметри】

W  t_mask  Маска типів повідомлень, для яких призначається обробник
FP msghdr  Вказівник на функцію обробника або системна константа:
           = MH_NONE  : Ігнорування повідомлень
           = MH_BREAK : Переривання очікування (ER_MINTR)
           = MH_TERM  : Аварійне завершення процесу
           = NULL     : Скидання на стандартний обробник (MH_NONE)

【Значення, що повертається】

= 0      Успішне виконання (E_OK)
< 0      Помилка (Код помилки)

【Детальний опис】

Реєструє функцію обробника msghdr для повідомлень, маска типів яких збігається з t_mask.

【Коди помилок】

ER_ADR   : Неприпустима адреса вказівника функції msghdr у пам'яті.
ER_PAR   : Неприпустиме значення маски (t_mask <= 0).
ret_msg
 
Завершення обробки повідомлення (Return from Message Handler)

【Синтаксис / Прототип】

ERR ret_msg(W ret)

【Параметри】

W ret    Режим повернення:
         = 0 : Повернення у точку переривання основної програми
         != 0 : Підготовка до нелокального переходу longjmp()

【Значення, що повертається】

Не повертає управління (при ret = 0)
= 0      Успішне виконання (при ret != 0 перед викликом longjmp)

【Детальний опис】

Системний виклик для виходу з функції обробника повідомлень. Повідомляє ядро про завершення асинхронної обробки і відновлює стан процесу.

【Коди помилок】

Помилок немає.

brk_msg
 
Переривання очікування повідомлення (Break Waiting Message)

【Синтаксис / Прототип】

ERR brk_msg(VOID)

【Параметри】

Відсутні (VOID)

【Значення, що повертається】

= 0      Успішне виконання (E_OK)

【Детальний опис】

Примусово перериває стан очікування для задачі власного процесу, заблокованої системним викликом rcv_msg() у режимі WAIEVT.

【Коди помилок】

Помилок немає (завжди повертає E_OK).


Повернутися до змісту цього розділу
Попередня сторінка: 1.1 Управління процесами та задачами (Повернутися)
Наступна сторінка: 1.3 Синхронізація та комунікація задач (Перейти)