Вітаю.
Відразу попереджу, що піст сповнений особистих міркувань автора, які можуть бути помилковими, та й тема ця велика і цікава, так що обговорення по темі в коментарях вітається.
Тільки зараз усвідомив, що по-перше, не розповів я багато чого, що корисно було б знати перед тим, як писати код. До того ж є набагато більш хороші шляхи для реалізації багатозадачності, ніж я згадував у минулому випуску.
Також постараюся наслідувати численні поради і систематизувати зміст статей.
Незважаючи на те, що цей випуск - белетристика чистої води, складемо план.
1) Різні думки про реалізацію багатозадачності.
2) За і проти за кожен спосіб.
3) Вирішимо як робити свій велосипед.
Приступимо.
1) Коли я тільки почав роздумувати як же сабж краще реалізувати, закралася до мене сакральна, прямолінійна думка. Ось подумаємо про область, де процеси користувача виконуються (з ring0 все простіше). Давайте виділимо їм місце, починаючи з 16 мегабайт. Решта - їх область, до самого кінця оперативки. Тепер виникає питання: як же нам контролювати і забезпечувати процес всім необхідним. Сакральна думка полягала в наступному, ви її вже чули: ділимо RAM на N шматків (не обов'язково рівних), потім організуємо черги із завдань і до них, будемо робити заміри по'вазі'програм в. т.д. Ви, напевно, хочете вже сказати: "Автор, може, видаси бойовий вигляд і понесешся грабувати села? По-варварськи все це ".. Згоден. Така модель нежиттєздатна, нерозширяєма і жахливо неефективна. Про це писав усім відомий товариш Таненбаум у своїй чудовій праці. При такій реалізації багатозадачності виникають такі проблеми: маленьким програмам буде приділятися менше часу, можливе голодування. Через те, що розміри у всіх програм різні, а рамки статичні, буде виникати нерівноправна конкуренція. В принципі, це можна вирішити суворим контролем, але вже боляче багато цей метод зі статичними розділами приносить головного болю.
2) Потім, трохи подумавши, прийшла на думку й інша думка: віртуальна пам'ять.
Давайте краще згадаємо про сторінкову організацію пам'яті (благослови її Ктулху).
Якщо ми не використовуємо статичні області для завдань, то виникає ряд інших проблем:
1) Як же стежити за зростаючими процесами?
2) Чи не позатирають один одного?
3) Чи потрібен у фізичній пам "яті шматок безперервного простору для процесу?
Давайте з ними розберемося.
1) Для того, щоб не упустити процеси достатньо реалізувати менеджер (менеджер) пам'яті, який і буде «роздавати пайки» у вигляді вільних сторінок. До того ж кожному процесу ми даруємо свої власні дескриптори, які і повідрубають довгі ручонки процесу.
2) Ось це ще один обов'язок диспетчера - ретельно стежити за тим, щоб пам'ять не використовувалася спільно N процесами.
3) Чесно, спочатку я сам помилявся, ДЕ ж виконується код у фізичному або віртуальному просторах (знаю, дивно звучить). Відповідь - у віртуальному просторі. Просто уявіть світи як у Матриці: обидва пов'язані, і обидва реальні. Так що не треба сприймати віртуальний простір як нічого не значущий і просто розширює максимальний обсяг адресованої оперативки.
Щоб ліпше зрозуміти, розгляньмо приклад. Ось, припустимо, є якийсь процес, частинки якого розкидані по всій фізичній пам'яті. Але ж ми можемо призначити сторінкам з певними віртуальними адресами фізичні адреси, правді ж? Тобто віртуальна адреса знову відправиться в подорож по каталогах і сторінках, а в кінці буде цілком собі потрібна і валідна адреса у фізичній пам'яті. Виходить, що для процесу віртуальні адреси будуть послідовними, але насправді його код може де завгодно валятися у фізичній пам'яті.
Спосіб, описаний вище, використовується зараз у багатьох операційках, так він досить стабільний, гнучкий. Складність буде тільки в грамотному написанні якісного коду.
Ось тепер непомітно підійшли до теми менеджера пам'яті. Взагалі то вважається, що це найскладніша частина в проекті. Навіть чув такий жарт:
"Чому osdev проекти глухнуть?
1) Сильно зайнятий на роботі;
2) Одружився;
3) Спробував написати менеджер пам'яті; "
Але не будемо лякатися. Постараємося впоратися. Він повинен буде «справедливо правити», щоб в оперативці панувала ідилія і «золотий вік»:
1) Стежити за сторінками: вчасно їх звільняти, ремапити.
2) Шукати нові вільні сторінки за запитом (# PF, найчастіше).
Для цього передбачено кілька алгоритмів, які також описані у товариша Таненбаума. Розгляньмо їх пізніше.
3) Якщо стало недостатньо фізичної пам'яті, то використовувати своп. При такому розкладі потрібно буде знайти менш використовувані сторінки, заганяти їх у своп. Потім назад. Коротше кажучи, доведеться менеджеру неабияк попотіти в такому випадку.
Тепер давайте опишемо на словах, як же буде відбуватися створення нового завдання (враховуємо, що це поки ще не боєздатна версія):
1) Перевірити, чи є взагалі місце ще для одного завдання.
2) Завантажити спосіб програми в пам'ять за певною адресою.
3) Описати для завдання дескриптори коду, стека, даних.
4) Було б красиво, якби створили свій каталог сторінок для завдання з усіма витікаючими.
5) Передати управління кодом програми.
6) Якщо виникає # PF, то дивимося, яке завдання виконувалося, при зверненні до якої адреси воно пофарбувалося, волаємо з благаннями до менеджера пам'яті і, якщо пощастить, отримуємо ще одну сторінку пам'яті, і повертаємося назад до коду.
У наступному випуску розглянемо, як же писати горезвісний менеджер пам'яті, адже без нього нікуди не дінешся.
Що почитати:
1) Ендрю Таненбаум: «Сучасні операційні системи». (Дуже корисна книга).
2) Intel System Programming Manuals (без них нікуди).
