Перейти до вмісту

Що таке ОС і навіщо вона

Коли ви пишете fopen("data.txt"), вам не треба знати ні модель диска, ні номер сектора, ні те, що в цю саму секунду до диска звертаються ще дві сотні процесів. Коли пишете malloc(1024), ніхто не питає дозволу в сусідніх програм.

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

Зазвичай кажуть, що операційна система керує ресурсами. Це правда, але неповна, і друга половина цікавіша.

Перше, що робить ОС, — вигадує зручні поняття там, де їх немає. Апаратура надає жахливий інтерфейс: регістри контролера, номери секторів, переривання. Працювати з цим напряму можна, але дуже не хочеться. Тому ОС дає натомість файл, процес, сокет. Жодної з цих речей в залізі не існує, вони цілком вигадані.

Друге — це справді розподіл. Процесор один, а програм двісті; пам’ять скінченна, а апетити ні. Хтось має вирішувати, кому скільки дати, і стежити, щоб одна програма не зіпсувала життя іншим.

Обидві задачі впираються в одне й те саме: ізоляцію. Абстракція, яку можна обійти, нічого не варта, бо тоді програма просто запише на диск напряму й зруйнує все, що ОС побудувала. Тож ОС мусить бути єдиною, хто взагалі має право говорити з апаратурою.

Рівні системи від застосунків до апаратури з апаратно захищеною межею між режимом користувача і режимом ядра застосункибраузер, компілятор, ваш кодбібліотеки й середовища виконанняlibc, JVM, Node — усе ще режим користувачаядро операційної системипроцеси, пам’ять, файли, мережа, драйвериапаратне забезпеченняпроцесор, пам’ять, диски, мережеві картирежим користувачарежим ядрасистемний виклик — єдиний легальний перехід ↓
Бібліотеки, попри назву «системні», працюють у режимі користувача. Вони лише зручні обгортки над системними викликами, а справжня межа проходить нижче.

Процесор уміє виконувати код щонайменше у двох режимах. У режимі ядра доступні всі інструкції: можна перепрограмувати MMU, вимкнути переривання, звернутися до порту пристрою. У режимі користувача спроба зробити те саме викликає виняток.

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

Звідси, до речі, стає зрозуміло, що є частиною ОС, а що ні. libc не є ядром: вона працює в режимі користувача. Оболонка теж звичайна програма. А от драйвер — ядро, бо звертається до заліза напряму.

Історію ОС можна прочитати як список дат, але тоді вона нічого не пояснює. Значно корисніше дивитися, чого саме бракувало в кожен момент.

У п’ятдесятих бракувало машинного часу. Комп’ютер коштував як завод, і простій між задачами був неприпустимий. Так з’явилася пакетна обробка: завдання складають у чергу, монітор запускає їх одне за одним, оператор не потрібен. Це і була перша програма, яка керує іншими програмами.

У шістдесятих виявилося, що процесор більшість часу нічого не робить, поки задача чекає на стрічку. Відповіддю стало мультипрограмування: тримати в пам’яті кілька задач і перемикатися на іншу, поки перша чекає. Звідси відразу виросли дві теми, які займають половину цього курсу, — захист пам’яті (задачі не мають бачити одна одну) і планування (модуль 7).

Далі почала дратувати вже сама людина за терміналом: у пакетному режимі результату доводилося чекати добу. Розв’язком став поділ часу, коли кожному дістається квант процесора достатньо часто, щоб робота здавалася інтерактивною. З цієї ідеї виріс Multics, а з роздратування його складністю — Unix.

У вісімдесятих комп’ютер став персональним, дефіцит користувачів зник, а разом із ним чомусь зникла й потреба в захисті. Ранні MS-DOS і Mac OS не мали ні захисту пам’яті, ні витісняльної багатозадачності, тож одна помилка вішала машину. Повертати ці властивості довелося наступні півтора десятиліття.

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

А потім частота процесорів перестала зростати. Замість швидших ядер почали ставити більше ядер, а на ноутбуках і телефонах додалося ще одне обмеження — заряд батареї. Тож планувальник тепер зважає не лише на швидкість, а й на витрату енергії, топологію NUMA і різнорідні ядра.

Наскільки різними бувають ОС

Section titled “Наскільки різними бувають ОС”

Словосполучення «операційна система» означає дуже різні речі залежно від того, чим вона керує.

Клас Приклади Що визначає дизайн
Вбудовані без ОС прошивка мікроконтролера кілька кілобайтів пам’яті, одна задача
RTOS FreeRTOS, Zephyr, QNX передбачуваність важливіша за пропускну здатність
Мобільні Android, iOS батарея, ізоляція застосунків, дозволи
Настільні Windows, macOS, Linux час відгуку, різноманіття заліза
Серверні Linux пропускна здатність, час безвідмовної роботи
Гіперскейлери гіпервізори, оркестратори тисячі машин як один ресурс

Систему реального часу від решти відрізняє не швидкість, як часто думають, а передбачуваність. RTOS гарантує, що реакція настане не пізніше певного строку. Для гальм автомобіля стабільні 10 мс кращі за «зазвичай одна мілісекунда, але іноді сто».

Terminal window
uname -a; cat /proc/version

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

Terminal window
ls /boot/vmlinuz-* 2>/dev/null; lsmod | head -5

Ядро — це файл на диску. lsmod покаже модулі, довантажені до нього під час роботи: драйвери й підсистеми, які необов’язково тримати всередині.

Terminal window
ps -p 1 -o pid,comm,args

Процес із PID 1 запускається ядром першим у режимі користувача, і все інше в системі є його нащадками (модуль 5).

Terminal window
ltrace -e 'malloc+free' -- /bin/echo hi 2>&1 | head -5
strace -c -- /bin/echo hi 2>&1 | tail -12

Перша команда показує виклики бібліотеки, друга — системні виклики. Різниця між цими двома списками і є та межа з рисунка вище.

Типові помилки розуміння

Section titled “Типові помилки розуміння”

«ОС — це те, що я бачу на екрані». Графічна оболонка складається зі звичайних програм у режимі користувача. Сервер без монітора має цілком повноцінну ОС і жодного вікна.

«ОС керує ресурсами». Керує, але це половина роботи. Друга половина в тому, щоб створити абстракції, яких в апаратурі просто немає.

«Ядро повільніше за програму, бо додає прошарок». Ядро не стоїть на шляху кожної операції. Обчислення виконує процесор напряму, а ядро втручається лише на системних викликах, перериваннях і винятках.

«Системи реального часу — найшвидші». Вони найпередбачуваніші. За середньою пропускною здатністю RTOS часто програє Linux.

«Linux — це операційна система». Строго кажучи, Linux це ядро. Те, що ви встановлюєте, називається дистрибутивом: ядро плюс libc, оболонка, система ініціалізації і тисячі пакетів.

Перевір себе

1. Які дві основні задачі виконує операційна система?
2. Чому програма не може самостійно перейти в режим ядра?
3. Яке апаратне обмеження породило мультипрограмування?
4. Чим система реального часу принципово відрізняється від звичайної?
5. libc — це частина ядра?
6. Чому Unix витіснив попередні системи й дожив до сьогодні у вигляді Linux, macOS та Android?
  • OSTEP, Introduction to Operating Systems
  • Silberschatz, Operating System Concepts, розділ 1
  • Таненбаум, Modern Operating Systems, розділ 1
  • The UNIX Time-Sharing System — Рітчі й Томпсон, 1974
  • Айзексон, Інноватори — історія галузі як історія людей