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

1.1 Управління процесами та задачами (Process & Task Management)

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

1.1.1 Процеси та задачі (Processes & Tasks)

Процес (Process) — це базова одиниця управління програмою з боку ОС. В системі може одночасно існувати кілька процесів.

Задача / потік (Task) — це одиниця виконання коду. Кожен процес містить одну або кілька задач, які виконуються паралельно за допомогою планувальника на основі пріоритетів та квантування часу (Time-Sharing).

Кожен процес має власне ізольоване віртуальне адресне середовище (Address Space), як показано на схематичному малюнку нижче.

Базова модель пам'яті процесу BTRON
Мал. 1: Базова модель пам'яті процесу BTRON

Процес створюється шляхом вказівки виконуваного файла програми та ідентифікується унікальним числовим ідентифікатором процесу (PID). PID — це додатне ціле число, яке призначається послідовно в порядку зростання.

При створенні процесу автоматично запускається його головна задача (Main Task). Головна задача може породжувати додаткові підзадачі (Subtasks), завдяки чому процес може мати 1 головну задачу та 0 або більше підзадач.

Головні задачі та підзадачі узагальнено називаються задачами (Tasks). Кожна задача ідентифікується додатним ідентифікатором задачі (Task ID / TID).

При завантаженні системи спочатку створюється системний початковий процес (Init Process), який послідовно породжує всі інші необхідні процеси. Процес, створений даним процесом, називається дочірнім процесом (Child Process), а процес, що його створив — батьківським процесом (Parent Process). Системний початковий процес не має батьківського процесу. Таким чином, уся сукупність процесів у системі утворює деревоподібну ієрархічну структуру з початковим процесом у корені.

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

1.1.2 Стан процесів та задач (Process & Task States)

Визначено 4 основні стани процесу (стан процесу відповідає стану його головної задачі):

Неіснуючий стан(Non-Existent)-- Процес ще не створено або вже знищено
Готовий до виконання(Ready)-- Процес готовий до роботи та очікує виділення процесорного часу (Dispatch)
Стан виконання(Run)-- Процес виконується на процесорі в даний момент
Стан очікування(Wait)-- Процес заблоковано в очікуванні події, повідомлення, таймера або вводу-виводу

Перехід між станами здійснюється через системні виклики та діями планувальника (Dispatching / Preemption), як показано на діаграмі:

Діаграма переходу станів процесів та задач
Мал. 2: Діаграма переходу станів процесів та задач

Поточний стан процесу зчитується у вигляді структури P_STATE:

typedef struct {
    UW  state;      /* Стан процесу (Process State) */
    W   priority;   /* Поточний пріоритет процесу (0..255) */
    W   parpid;     /* PID батьківського процесу */
} P_STATE;

Слово стану процесу (Process State Word / state) містить набір прапорців, де значення «1» вказує на активність відповідного стану.

Слово стану процесу (Process State Word)
Мал. 3: Слово стану процесу (Process State Word)

Підзадачі мають аналогічні стани та переходять за тими ж правилами.

При завершенні процесу всі його задачі автоматично припиняють виконання. Також завершення головної задачі призводить до примусового припинення всіх підзадач та завершення процесу. Завершення окремої підзадачі не призводить до завершення всього процесу.

1.1.3 Пріоритети та планування задач (Priorities & Scheduling)

При створенні процесу йому призначається пріоритет у діапазоні 0 – 255 (де 0 — найвищий пріоритет). Цей пріоритет встановлюється для його головної задачі. Поняття «пріоритет процесу» є еквівалентним пріоритету його головної задачі.

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

A. Група абсолютного пріоритету (Absolute Priority Group, пріоритети: 0 - 127)

Планування здійснюється суворо за пріоритетом (0 — найвищий пріоритет). Задачі з однаковим пріоритетом плануються циклічно за алгоритмом Round-Robin.

B. Група циклічного планування Round-Robin Group 1 (пріоритети: 128 - 191)

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

C. Група циклічного планування Round-Robin Group 2 (пріоритети: 192 - 255)

Аналогічно до групи 1, здійснюється циклічне планування для фонових задач (192 — найвищий пріоритет у даній групі).

Порядок роботи глобального планувальника задач:

  1. 1. Якщо в абсолютній групі є готові задачі (Ready), планувальник обирає задачу з найвищим пріоритетом і запускає її (Run). Якщо ні — переходить до п. 2.

  2. 2. Якщо в групі Round-Robin 1 є готові задачі (Ready), згідно з їхнім відносним пріоритетом обирається задача, переводиться в стан виконання (Run) і запускається. Якщо готових задач немає — переходить до п. 3.

  3. 3. Якщо в групі Round-Robin 2 є готові задачі (Ready), обирається задача відповідно до її відносного пріоритету, переводиться в стан виконання (Run) і запускається. Якщо готових задач немає — цикл планування відновлюється з самого початку.

Зазвичай група абсолютного пріоритету використовується для системних ядерних та системних систем реального часу (Real-Time System Processes), а стандартні прикладні програми використовують групи Round-Robin 1 або 2.

Зміна пріоритету вже створеного процесу або задачі дозволена лише у межах її початкової групи (зміна групи планування заборонена).

1.1.4 Середовище виконання процесів (Execution Environment)

Для кожного процесу система зберігає наступне середовище виконання (Execution Environment):

При створенні нового дочірнього процесу викликом cre_prc() його початкове середовище ініціалізується наступним чином:

Елемент середовищаЗначення для нового дочірнього процесу
PID власного / батьківського процесуПризначений унікальний PID / PID батьківського процесу
Пріоритет процесуЗначення, вказане при створенні cre_prc()
Дані користувачаУспадковуються від батьківського процесу
Поточний робочий файлУспадковується від батьківського процесу
Відкриті файлиВідсутні (порожній список)
Черга повідомленьПорожня черга

1.1.5 Системні дані користувача (User Information)

Системні дані користувача містять інформацію про власника та права доступу процесу:

typedef struct {
    TC  usr_name[14];   /* Ім'я користувача (12 символів + 2 приховані) */
    TC  grp_name1[14];  /* Назва групи 1 (12 символів + 2 приховані) */
    TC  grp_name2[14];  /* Назва групи 2 (12 символів + 2 приховані) */
    TC  grp_name3[14];  /* Назва групи 3 (12 символів + 2 приховані) */
    TC  grp_name4[14];  /* Назва групи 4 (12 символів + 2 приховані) */
    W   level;          /* Рівень привілеїв користувача (0..15) */
    W   net_level;      /* Мережевий рівень привілеїв (1..15) */
} P_USER;

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

1.1.6 Створення та запуск процесів (Process Creation)

Створення процесу виконується шляхом вказівки цільового виконуваного файла, пріоритету процесу та початкового повідомлення запуску.

Перший виконуваний запис у вказаному Реальному об'єкті стає програмним кодом нового процесу. Цей запис повинен бути першим у файлі.

Початкове повідомлення описується вказівником на структуру MESSAGE:

typedef struct {
    W   msg_type;       /* Тип повідомлення */
    W   msg_size;       /* Розмір повідомлення у байтах */
    UB  msg_body[n];    /* Тіло повідомлення (msg_size байт) */
} MESSAGE;

Створений процес може приймати початкове повідомлення в одному з 2 форматів. Повернення з функцій MAIN() чи main() є еквівалентним виклику ext_prc(), а повернутий код передається батьківському процесу:

□ Формат A

W MAIN (MESSAGE *msg)
{
    /* msg — вказівник на початкове системне повідомлення */
    < Код виконання програми >
    return код_завершення;
}

□ Формат B

W main (W ac, TC **argv)
{
    /* ac — кількість аргументів командного рядка */
    /* argv — масив вказівників на аргументи-рядки TRON Code */
    < Код виконання програми >
    return код_завершення;
}
main() аргументи
Мал. 4: Структура передачі аргументів у main()

1.1.7 Виконання та синхронізація процесів/задач

Задачі процесу виконуються паралельно. Окрім основного потоку, ядро може асинхронно викликати наступні системні обробники (функції-інтеррапти):

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

Асинхронні функції, що активуються при надходженні системних повідомлень (див. «1.2.3 Обробники повідомлень»).

Обробники системних винятків (Exception Handlers)

Асинхронні функції, що викликаються при системних збоях або винятках процесу (див. «1.10 Загальне системне управління»).

Поточний стан використання ресурсів процесу зчитується структурою P_INFO:

typedef struct {
    UW  etime;      /* Сумарний час існування процесу (секунди) */
    UW  utime;      /* Сумарний CPU-час коду користувача (мілісекунди) */
    UW  stime;      /* Сумарний CPU-час коду ядра (мілісекунди) */
    W   tmem;       /* Загальний необхідний розмір пам'яті (байти) */
    W   wmem;       /* Виділена фізична пам'ять (байти) */
    W   resv[11];   /* Зарезервовано */
} P_INFO;

1.1.8 Визначення типів даних та констант

□ Структури стану, користувача та статистики

typedef struct {
    UW  state;      /* Стан процесу */
    W   priority;   /* Поточний пріоритет (0..255) */
    W   parpid;     /* PID батьківського процесу */
} P_STATE;

typedef struct {
    TC  usr_name[14];   /* Ім'я користувача (12 символів + 2 приховані) */
    TC  grp_name1[14];  /* Група 1 */
    TC  grp_name2[14];  /* Група 2 */
    TC  grp_name3[14];  /* Група 3 */
    TC  grp_name4[14];  /* Група 4 */
    W   level;          /* Рівень привілеїв (0..15) */
    W   net_level;      /* Мережевий рівень (1..15) */
} P_USER;

typedef struct {
    UW  etime;      /* Сумарний час (секунди) */
    UW  utime;      /* CPU-час користувача (мс) */
    UW  stime;      /* CPU-час ядра (мс) */
    W   tmem;       /* Загальна пам'ять (байти) */
    W   wmem;       /* Фізична пам'ять (байти) */
    W   resv[11];   /* Зарезервовано */
} P_INFO;

□ Системні константи процесів

#define TERM_NRM    0x0000      /* Завершення лише вказаного процесу */
#define TERM_ALL    0x0001      /* Примусове завершення дочірнього дерева */

#define P_ABS       0x0000      /* Абсолютний пріоритет */
#define P_REL       0x0001      /* Відносний пріоритет */
#define P_TASK      0x0002      /* Прапорець цільової задачі */

#define P_WAIT      0x2000      /* Стан очікування */
#define P_READY     0x4000      /* Стан готовності */
#define P_RUN       0x8000      /* Стан виконання */

1.1.9 Системні виклики ядра (Kernel System Calls)

cre_prc
 
Створення та запуск процесу (Create Process)

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

WERR    cre_prc(LINK* lnk, W pri, MESSAGE* msg)

【Параметри】

LINK*    lnk  Вказівник на посилання/дескриптор цільового Реального об'єкта (виконуваного файла)
W        pri  Пріоритет створюваного процесу
              0 <= pri <= 255  Довільний пріоритет
              = -1             Успадкувати пріоритет батьківського процесу
MESSAGE* msg  Початкове системне повідомлення запуску процесу

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

> 0      Успішне виконання (PID згенерованого дочірнього процесу)
< 0      Помилка (Код помилки)

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

Завантажує виконуваний запис програми з вказаного Реального об'єкта (lnk) та створює новий дочірній процес у системі. Одночасно автоматично ініціалізується та запускається його головна задача (Main Task).

Детальний опис процедур ініціалізації див. у розділі «1.1.6 Створення та запуск процесів».

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


ER_ACCES   : Відсутні необхідні права доступу (R/W/E) до вказаного об'єкта.
ER_ADR     : Неприпустима адреса вказівника у віртуальній пам'яті.
ER_BUSY    : Ресурс або файл заблокований у монопольному режимі іншим процесом.
ER_IO      : Критична помилка введення/виведення (I/O Error) пристрою.
ER_NOEXS   : Вказаний об'єкт, файл або ім'я відсутнє у системі.
ER_NOFS    : Файлова система або том зазначеного об'єкта не підключена (Unmounted).
ER_NOMEM   : Помилка виконання системного виклику.
ER_NOSPC   : Недостатньо оперативної пам'яті ядра для виконання операції.
ER_PPRI    : Помилка виконання системного виклику.
ER_REC     : Помилка виконання системного виклику.
ER_SZOVR   : Розмір файлу або об'єкта перевищує максимально припустимий системний ліміт.

ext_prc
 
Завершення власного процесу (Exit Process)

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

VOID    ext_prc(W code)

【Параметри】

W   code    Код завершення процесу (Exit Code)

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

Функція не повертає управління (процес знищується).

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

Нормально завершує виконання власного процесу і надсилає батьківському процесу системне повідомлення про нормальне завершення із кодом code.

Усі системні ресурси (дескриптори відкритих файлів, семафори з атрибутом DELEXIT) автоматично вивільняються ядром.

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

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

ter_prc
 
Примусове завершення іншого процесу (Terminate Process)

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

ERR     ter_prc(W pid, W code, W opt)

【Параметри】

W   pid Ідентифікатор цільового процесу (PID)
        >  0   Довільний процес
        =  0   Власний процес (заборонено: вертає ER_SELF)
        = -1   Батьківський процес
W   code    Код примувого завершення
W   opt Атрибути примусового завершення (TERM_NRM || TERM_ALL)
        TERM_NRM    Примусове завершення лише вказаного процесу.
        TERM_ALL    Примусове завершення вказаного процесу та всіх його дочірніх нащадків.

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

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

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

Примусово перериває та знищує вказаний процес (pid) і надсилає його батьківському процесу повідомлення про примусове завершення. Процес не може примусово завершити інший процес із вищим рівнем привілеїв.

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


ER_SELF    : Помилка виконання системного виклику.
ER_NOPRC   : Помилка виконання системного виклику.
ER_LEVEL   : Помилка виконання системного виклику.
ER_PAR     : Неприпустиме значення одного з параметрів системного виклику.

chg_pri
 
Зміна пріоритету процесу чи задачі (Change Priority)

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

WERR    chg_pri(W id, W pri, W opt)

【Параметри】

W   id  Ідентифікатор процесу (PID) або задачі (TID)
W   pri Новий рівень пріоритету
W   opt Режим зміни пріоритету (P_ABS || P_REL) | [ P_TASK ]
        P_ABS   Абсолютна зміна: пріоритет стає рівним pri.
        P_REL   Відносна зміна: новий пріоритет = (поточний пріоритет) + pri.
        P_TASK  Об'єктом зміни є конкретна задача TID.

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

>= 0     Успішне виконання (новий підтверджений пріоритет 0..255)
< 0      Помилка (Код помилки)

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

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

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


ER_ID      : Неприпустимий ідентифікатор ID об'єкта або процесу.
ER_PPRI    : Помилка виконання системного виклику.

cre_tsk
 
Створення та запуск підзадачі (Create Subtask)

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

WERR    cre_tsk(FP entry, W pri, W arg)

【Параметри】

FP  entry   Адреса точки входу функції підзадачі
W   pri     Пріоритет підзадачі
W   arg     Початковий параметр, що передається підзадачі

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

> 0      Успішне виконання (TID створеної підзадачі)
< 0      Помилка (Код помилки)

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

Створює та запускає нову підзадачу (Subtask) в адресному просторі власного процесу. Сигнатура функції підзадачі повинна відповідати виклику: VOID subtask(W arg) та обов'язково завершуватися викликом ext_tsk().

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


ER_ADR     : Неприпустима адреса вказівника у віртуальній пам'яті.
ER_PPRI    : Помилка виконання системного виклику.
ER_LIMIT   : Перевищено системний ліміт кількості відкритих об'єктів або файлів.
ER_NOMEM   : Помилка виконання системного виклику.

ext_tsk
 
Завершення поточної задачі (Exit Task)

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

VOID    ext_tsk(VOID)

【Параметри】

Відсутні (VOID)

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

Функція не повертає управління (задача знищується).

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

Завершує виконання поточної задачі. Якщо виклик виконується головною задачею (Main Task), це призводить до завершення всього процесу.

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

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

ter_tsk
 
Примусове завершення підзадачі (Terminate Subtask)

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

ERR     ter_tsk(W tskid)

【Параметри】

W   tskid   Ідентифікатор цільової підзадачі (TID)

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

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

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

Примусово завершує виконання вказаної підзадачі в рамках власного процесу. Заборонено примусово завершувати головну задачу або поточну задачу.

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


ER_ID      : Неприпустимий ідентифікатор ID об'єкта або процесу.

slp_tsk
 
Призупинення задачі / очікування (Sleep Task)

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

ERR     slp_tsk(W time)

【Параметри】

W       time    Максимальний інтервал таймауту у мілісекундах
                >  0   Очікувати вказану кількість мілісекунд
                = -1   Безкінечне очікування (до виклику wup_tsk)

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

= 0      Успішне виконання (задача розблокована викликом wup_tsk)
< 0      Помилка (Код помилки)

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

Переводить поточну задачу у стан очікування (Wait). Очікування припиняється при спливанні таймеру time або при отриманні сигналу пробудження wup_tsk() від іншої задачі.

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


ER_NONE    : Помилка виконання системного виклику.
ER_MINTR   : Обробку перервано внаслідок надходження системного сигналу.
ER_PAR     : Неприпустиме значення одного з параметрів системного виклику.

wup_tsk
 
Пробудження задачі (Wakeup Task)

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

ERR     wup_tsk(W tskid)

【Параметри】

W   tskid   Ідентифікатор цільової задачі (TID)

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

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

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

Пробуджує вказану задачу tskid зі стану очікування slp_tsk(). Якщо задача не перебувала в стані очікування, запит пробудження заноситься у чергу. Виклик дозволений лише для задач власного процесу.

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


ER_ID      : Неприпустимий ідентифікатор ID об'єкта або процесу.
ER_LIMIT   : Перевищено системний ліміт кількості відкритих об'єктів або файлів.

can_wup
 
Скасування запитів пробудження (Cancel Wakeup Requests)

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

WERR    can_wup(W tskid)

【Параметри】

W   tskid   Ідентифікатор цільової задачі
            > 0     Довільна задача власного процесу
            = 0     Власна задача

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

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

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

Очищає та скасовує всі накопичені чергові запити пробудження (Wakeup Requests) для вказаної задачі tskid у межах власного процесу.

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


ER_ID      : Неприпустимий ідентифікатор ID об'єкта або процесу.

dly_tsk
 
Затримка виконання задачі (Delay Task / Yield)

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

ERR     dly_tsk(W time)

【Параметри】

W   time    Час затримки у мілісекундах (time >= 0)

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

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

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

Призупиняє виконання поточної задачі на вказаний інтервал time (у мілісекундах).

Якщо вказано time = 0, задача добровольно віддає залишок процесорного часу, переходячи зі стану виконання (Run) у стан готовності (Ready) для виконання процедури перепланування процесора (Yield).

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


ER_MINTR   : Обробку перервано внаслідок надходження системного сигналу.
ER_PAR     : Неприпустиме значення одного з параметрів системного виклику.

get_tid
 
Отримання ID власної задачі (Get Task ID)

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

W   get_tid(VOID)

【Параметри】

Відсутні (VOID)

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

> 0      Успішне виконання (TID власної задачі)

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

Повертає системний ідентифікатор поточної задачі (TID).

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

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


Повернутися до змісту цього розділу
Попередня сторінка: Розділ 5 Ядро операційної системи (Повернутися)
Наступна сторінка: 1.2 Система повідомлень (Перейти)