Системний виклик (*syscall*) — єдина легальна межа
Диск і мережу програма читає лише через syscall: read, write, openat, execve, clone
Межа привілеїв: ядро не довіряє user space і робить небезпечне саме
Контейнер, компілятор Rust, Wasm-рантайм — зрештою про те, які syscalls дозволені
Кільця захисту (Ring 0 / Ring 3)
Ring 0 (kernel mode) — привілейований режим: ядро, драйвери, планувальник
Ring 3 (user mode) — звичайні програми без привілейованих інструкцій
Привілейована інструкція з Ring 3 → апаратний виняток (general protection fault)
Інструкція syscall — контрольований «місток» з Ring 3 у Ring 0 і назад
Межа в цифрах
450+
системних викликів
ядро Linux на x86-64
2
кільця, що реально використовує Linux
Ring 0 · Ring 3
1
інструкція переходу
syscall — і назад sysret
0
прямих доступів до заліза з Ring 3
диск, мережа, MMU — лише через ядро
libc ховає syscalls за printf, malloc, fopen — але знизу завжди вони
Побачити syscalls наживо
bash
strace-cls > /dev/null
# short summary: скільки викликів read/write/openat/execve...
strace показує реальний діалог програми з ядром
Живе демо: анатомія процесу
Запустити sleep 300 & і зберегти PID
Показати процес у ps aux | grep sleep
cat /proc/$PID/status — стан, пам'ять, батько
cat /proc/$PID/maps — сегменти адресного простору
ls /proc/$PID/fd — відкриті дескриптори
Очікувано: Студенти бачать: процес у ps — це рядок, а в /proc — цілий каталог зі структурою пам'яті й дескрипторів
Адресний простір процесу
text — код програми (тільки читання, виконання)
data/bss — глобальні змінні
heap — динамічна пам'ять, росте вгору
stack — локальні змінні й виклики функцій, росте вниз
Кожен процес бачить СВІЙ простір 0…2^64 — ізоляція за замовчуванням
Сегменти адресного простору
Сегмент
Вміст
Права
Росте
text
машинний код програми
r-x
—
data / bss
глобальні змінні
rw-
—
heap
malloc / new; brk, mmap
rw-
↑ вгору
shared libs
libc.so та інші, через mmap
r-x
—
stack
локальні змінні, адреси повернення
rw-
↓ вниз
Ті самі регіони — рядки у /proc/<pid>/maps; права видно в другій колонці
Перше входження: що таке контейнер
Контейнер — це **звичайний процес**, якому ядро підмінило видимість: свій список процесів, своя файлова система, своя мережа
Другого ядра немає. Немає гостьової ОС, немає емуляції заліза, немає BIOS
Усе з цієї лекції лишається чинним: PID, адресний простір, дескриптори, системні виклики — просто вміст /proc інший
Одне речення, яке варто запам'ятати: контейнер — це процес із підміненою мапою світу
Це відповідь лише на «що це таке». Як ядро це робить — Лекція 3; звідки береться образ — Лекція 2.
Яку проблему це вирішує
Як було: «працює в мене»
Залежності ставили руками на кожній машині
Версії компілятора й бібліотек розходилися між розробниками
«А в тебе яка версія clang?» — і півдня на з'ясування
Перенести проєкт на іншу машину = повторити всю установку
docker run
Як із контейнером
Середовище описане текстом і однакове в усіх
Версії зафіксовані там само, де код
Запуск однією командою: docker run
Зламав середовище — видалив контейнер і підняв новий за секунди
Саме тому середовище всіх десяти лабораторних курсу живе в контейнері, а не у твоїй системі.
Як це виглядає: що ти запустиш сьогодні
bash
docker run --rm-it ubuntu:24.04 bash
# ти всередині; далі — три команди, які показують межуcat /etc/os-release # Ubuntu 24.04 — навіть якщо в тебе Fedora чи macOS
uname -r # ядро — ХОСТА, не контейнера. Воно однеps aux # список процесів короткий: ти тут майже сам
Той самий bash-бінарник, інша мапа світу. Це і є вся магія.
Чим контейнер НЕ є
**Не віртуальна машина**: у ВМ є власне ядро й емульоване залізо, у контейнера — ні
**Не «легка ВМ»**: різниця не у вазі, а в тому, ХТО ізолює — ядро, а не гіпервізор
**Не пісочниця за замовчуванням**: root у контейнері за замовчуванням — це root на ядрі хоста (як це обмежують — Лекція 3)
**Не образ**: образ — це те, з чого контейнер запускається; контейнер — це запущений процес (Лекція 2)
Ці чотири плутанини — найчастіші на першому тижні. Якщо їх зняти, решта модуля йде легко.
Чому Docker — перша межа курсу
Docker не віртуалізує залізо — ізолює одне ядро для кількох процесів
Найдешевша й найближча до звичайного процесу форма ізоляції
Розуміння процесу з цієї лекції — основа для namespaces у Лекції 3
Мета абстракції — не бути розпливчастим, а створити новий семантичний рівень, на якому можна бути абсолютно точним.
— Едсгер Дейкстра, «The Humble Programmer» (1972)
Наперед: перший контейнер
bash
docker run --rm-it ubuntu:24.04ps aux
# у контейнері PID 1 — це наш процес, а не системний init хоста
Сьогодні ввечері на ЛР1 ти піднімеш такий контейнер сам
Підводні камені: процес і syscalls
PID — лише ключ пошуку; реальний стан живе в task_struct ядра
fork() не копіює пам'ять миттєво — copy-on-write відкладає до першого запису
strace бачить лише межу user↔kernel, а не виклики бібліотечних функцій
/proc — живий, не знімок: значення змінюються між двома cat
Підсумок
Процес — активна абстракція ядра: PID, адресний простір, дескриптори, права
Системний виклик — єдина легальна межа між програмою і машиною
Курс тричі повертається до цієї межі: Docker, Rust, WebAssembly
Наступного разу: як з інструкцій у текстовому файлі народжуються бінарні шари образу
🥚 У прикладах /proc фоновий процес має PID 3101 — шістнадцятково 0xC1D. Це не випадковість: таке число трапиться в курсі ще не раз.
VTFK · TERMLINK · L01← → · space · f — на весь екран