Операционные системы

Ввод-вывод

Процессор в миллион раз быстрее жёсткого диска. Один случайный read с HDD = 10 миллионов инструкций CPU впустую. Сеть передаёт гигабайты, видеокарта рендерит 60 кадров в секунду, диск пишет логи - всё это I/O. Эффективное управление вводом-выводом отделяет тормозящую программу от молниеносной. Понимание I/O - это понимание того, почему системы работают быстро или медленно.

  • **Почему игры грузятся быстрее на SSD?** HDD: seek 5мс × 10000 файлов = 50 секунд только на поиск. SSD: seek 0.1мс → та же операция за 1 секунду. Понимание I/O объясняет 50x разницу.
  • **Как nginx обрабатывает 100000 соединений на одном сервере?** Секрет: epoll (асинхронный I/O). Один процесс ждёт событий от тысяч сокетов, CPU не блокируется. Без epoll понадобилось бы 100000 потоков - коллапс.
  • **Почему серверы используют RAID?** Диск живёт в среднем 4 года. Сервер с 20 дисками переживает сбой каждые 2 месяца. RAID 6 позволяет работать при 2 мёртвых дисках - сервис не падает, данные сохранны.

Цели урока

  • Различать device controllers, drivers, interrupts, DMA
  • Сравнить I/O methods: programmed I/O, interrupt-driven, DMA по CPU overhead
  • Знать disk scheduling: FCFS, SSTF, SCAN, C-SCAN, LOOK
  • Понимать RAID levels: 0 (stripe), 1 (mirror), 5 (parity), 10 (stripe+mirror) и trade-offs
  • Применять буферизацию: page cache, double buffering, scatter-gather I/O

Аппаратура ввода-вывода

**Устройства ввода-вывода (I/O devices)** - это глаза, уши и руки компьютера. Клавиатура, мышь, диск, сетевая карта, видеокарта - всё это I/O устройства. Процессор в 1000 раз быстрее самого медленного I/O устройства, поэтому эффективное управление I/O критично для производительности.

**Классификация I/O устройств:** 1. **Block devices** (блочные) - работают блоками данных: HDD, SSD, USB-флешки 2. **Character devices** (символьные) - потоковые данные: клавиатура, COM-порт, терминал 3. **Network devices** - сетевые карты (особый случай)

**Анатомия I/O устройства.** Каждое устройство состоит из двух частей: 1. **Контроллер** (hardware) - микросхема, управляющая устройством. У контроллера есть **регистры** для команд и данных. 2. **Драйвер** (software) - код в OS, который знает, как общаться с конкретным контроллером.

Пример: чтение с диска

Когда программа вызывает `read()`, происходит цепочка: 1. **Syscall** → ядро 2. **VFS** находит драйвер файловой системы 3. **Драйвер диска** пишет команду READ в регистр контроллера 4. **Контроллер** двигает головку диска, читает сектор 5. **Данные** передаются в память через DMA (Direct Memory Access) 6. **Прерывание** уведомляет CPU, что операция завершена

**Memory-Mapped I/O (MMIO).** Современные контроллеры устройств "видны" как участки памяти. Драйвер пишет в адрес 0xFEDC000 - на самом деле это регистр сетевой карты. CPU не различает - это просто store в память.

**Port-Mapped I/O (PMIO).** Альтернатива MMIO: специальные инструкции процессора `IN/OUT` (x86). Используется редко, в основном legacy-устройствами.

Чем Memory-Mapped I/O (MMIO) отличается от Port-Mapped I/O (PMIO)?

Методы управления I/O

Как процессор узнаёт, что устройство закончило операцию? Существует три основных метода: **Polling (опрос)**, **Interrupts (прерывания)**, **DMA (прямой доступ к памяти)**. Каждый метод - trade-off между простотой и эффективностью.

**1. Polling (программируемый опрос).** Самый простой метод: CPU в цикле проверяет статус устройства. "Готово ли? Нет. Ещё нет. Теперь да!" Просто, но расточительно - CPU занят бесполезным ожиданием.

**2. Interrupts (прерывания).** Устройство "стучится" к CPU через специальный сигнал, когда готово. CPU в это время занят другой работой. Прерывание приходит → CPU сохраняет контекст → обрабатывает → возвращается. Эффективно!

Прерывания как дверной звонок

Аналогия: ожидание курьера. **Polling** - каждые 10 секунд подходить к двери и смотреть в глазок: "Приехал? Нет. Приехал? Нет." Время уходит впустую. **Interrupt** - у двери звонок. Можно заниматься своими делами, а когда курьер приходит - звонок прерывает работу. Эффективнее! Так и CPU: прерывание позволяет работать, пока диск крутится.

**3. DMA (Direct Memory Access).** Проблема: даже с прерываниями CPU должен копировать данные из буфера устройства в память. Для больших объёмов (видео, сеть) это медленно. **DMA контроллер** копирует данные напрямую в память, CPU вообще не участвует!

DMA в видеокартах

Когда видеокарта рендерит кадр игры, она генерирует **гигабайты** данных в секунду (4K @ 60fps ≈ 1.5 GB/s). Если бы CPU копировал каждый пиксель, производительность упала бы в 10 раз. **DMA** позволяет GPU писать напрямую в видеопамять, минуя CPU. Поэтому игры работают плавно.

**Выбор метода I/O в зависимости от устройства:** - **Polling:** Простые embedded-системы, редкие события (кнопка нажата?) - **Interrupts:** Большинство устройств (клавиатура, мышь, таймеры) - **DMA:** Высокоскоростные устройства (диски, сеть, видео)

**Асинхронный I/O в Linux: select/poll/epoll.** Когда программа работает с тысячами сокетов (веб-сервер), блокирующий `read()` не подходит. **epoll** позволяет ждать событий от множества файловых дескрипторов одновременно.

Почему DMA (Direct Memory Access) критично важен для высокоскоростных устройств вроде сетевых карт 10 Gbit/s?

Алгоритмы планирования дисков

**Жёсткие диски (HDD)** - механические устройства. Головка чтения движется над вращающимися пластинами. Поиск данных (seek) - самая медленная операция (~5-10мс). Если приходят запросы на чтение секторов 10, 500, 25 - в каком порядке их выполнять? **Disk scheduling** оптимизирует порядок обслуживания.

**Параметры производительности HDD:** - **Seek time** (поиск) - движение головки к нужному цилиндру: 5-10 мс - **Rotational latency** (ожидание поворота) - ждём пока нужный сектор подъедет под головку: 4 мс (7200 RPM) - **Transfer time** (передача) - чтение данных: 0.1 мс для 4KB блока Seek time доминирует! Минимизация движения головки = максимум производительности.

**FCFS (First-Come, First-Served).** Простейший алгоритм: обрабатывать запросы в порядке поступления. Проблема: головка хаотично мечется по диску, большие seek time.

**SSTF (Shortest Seek Time First).** Выбирать ближайший запрос. Жадный алгоритм: локально оптимален, но может вызвать **starvation** (дальние запросы ждут бесконечно).

**SCAN (алгоритм "лифта").** Головка движется в одну сторону, обслуживая все запросы на пути, доходит до конца → разворачивается. Как лифт: едет вверх, останавливается на всех этажах, потом вниз.

**C-SCAN (Circular SCAN).** Улучшение SCAN: после достижения края головка мгновенно "телепортируется" в начало, начинает новый проход. Более равномерное время ожидания.

SCAN vs C-SCAN: аналогия с автобусом

**SCAN** - автобус ходит по кругу, но по одному маршруту туда, по другому обратно. Пассажир на конечной станции ждёт дольше. **C-SCAN** - автобус идёт только в одном направлении, на конечной быстро возвращается в начало (без остановок). Более справедливое распределение времени ожидания между всеми запросами.

**LOOK и C-LOOK.** Оптимизации SCAN/C-SCAN: головка не доходит до физического края диска (0 или 256), а разворачивается на последнем запросе. Экономия движения.

**Disk scheduling в эпоху SSD:** SSD (флеш-память) не имеет движущихся частей → seek time практически нулевой (0.1 мс). Порядок запросов не влияет на производительность! Современные OS используют **Deadline** или **BFQ (Budget Fair Queueing)** schedulers - они оптимизируют latency и fairness, а не движение головки.

Почему NVMe быстрее SATA

**SATA III:** Интерфейс для HDD, максимум 600 MB/s, одна очередь команд (32 запроса). Протокол оптимизирован под медленные диски. **NVMe (PCIe):** Разработан для SSD. Пропускная способность 3500 MB/s (PCIe 3.0 x4), **64000 очередей** по 64000 команд в каждой. Параллелизм + низкая latency (прямой доступ к CPU через PCIe). Поэтому NVMe SSD в 5-7 раз быстрее SATA SSD.

Какой алгоритм планирования диска гарантирует отсутствие starvation (вечного ожидания запросов)?

RAID: отказоустойчивость и производительность

**RAID (Redundant Array of Independent Disks)** - технология объединения нескольких дисков для увеличения надёжности, производительности или того и другого. Идея: используя 4 диска, можно создать систему, которая переживёт выход из строя любого диска (RAID 5), или читать данные в 4 раза быстрее (RAID 0).

**Основные уровни RAID:** - **RAID 0** (striping) - скорость, без отказоустойчивости - **RAID 1** (mirroring) - полное дублирование, 2x надёжность - **RAID 5** (striping + parity) - производительность + защита от 1 сбоя - **RAID 6** (double parity) - защита от 2 сбоев - **RAID 10** (1+0) - mirror of stripes, баланс

**RAID 0 (Striping): максимальная скорость, нулевая защита.** Данные разбиваются на блоки и распределяются по дискам. Файл 4MB при 4 дисках: каждый диск получает 1MB. Чтение/запись параллельно → скорость умножается на N. Но: если **любой** диск сломается - все данные потеряны.

RAID 0 для видеомонтажа

Профессиональный монтаж 4K видео требует скорости 500+ MB/s (несколько потоков одновременно). Один SSD даёт 500 MB/s, но для 8K нужно больше. **RAID 0 из 4 NVMe SSD** → 2000 MB/s. Данные не критичны (рабочие файлы, бэкап на сервере), важна скорость. Типичный use case для RAID 0.

**RAID 1 (Mirroring): полное дублирование.** Каждый байт записывается на 2 диска. Один диск умирает - данные на втором. Простая и надёжная схема. Недостаток: ёмкость делится пополам (2TB + 2TB = 2TB полезных).

**RAID 5 (Striping + Parity): баланс между производительностью и надёжностью.** Данные распределены по дискам (striping), плюс на каждый stripe вычисляется **контрольная сумма (parity)**, которая хранится на другом диске. Можно восстановить данные с любого сломанного диска по формуле: `D = A ⊕ B ⊕ P` (XOR).

RAID 5 в серверах

Типичный файловый сервер: 6 дисков по 4TB в RAID 5 → 20TB полезной ёмкости (вместо 24TB). Скорость чтения ~500 MB/s (почти как RAID 0), но с защитой: любой диск может сломаться, данные сохранны. Пока сломанный диск заменяется, система работает (degraded mode). После замены - автоматическое восстановление (rebuild).

**RAID 6 (Double Parity): защита от 2 сбоев.** Как RAID 5, но **два** parity блока на stripe (используют разные алгоритмы). Можно потерять любые 2 диска. Критично для больших массивов: rebuild RAID 5 может занять сутки, вероятность второго сбоя во время rebuild - высока.

**RAID 10 (1+0): Mirror of Stripes.** Сначала создаём пары зеркал (RAID 1), потом объединяем их в stripe (RAID 0). Например, 4 диска: (Диск1+Диск2) зеркало, (Диск3+Диск4) зеркало, два зеркала в RAID 0. Скорость чтения 4x, надёжность высокая, но ёмкость 50%.

**Hardware RAID vs Software RAID:** - **Hardware RAID:** Специальный контроллер с процессором, кешем, батарейкой (для защиты от сбоя питания). Не нагружает CPU, но дорого (500+). - **Software RAID:** Управляется OS (Linux mdadm, Windows Storage Spaces). Использует CPU для parity, но современные CPU справляются. Бесплатно, гибко. Тренд: Software RAID побеждает (ZFS, Btrfs встроенный RAID).

Ключевые идеи

  • **I/O устройства - узкое место.** CPU в 1000+ раз быстрее диска. Эффективное управление I/O критично: DMA освобождает процессор от копирования данных, прерывания избавляют от бесполезного ожидания (polling). Без этого система тормозит.
  • **Три метода управления I/O: Polling, Interrupts, DMA.** Polling - простой, но расточительный (CPU крутится в цикле). Interrupts - эффективный (CPU работает, устройство "стучится" когда готово). DMA - для больших объёмов (устройство пишет в память напрямую, CPU свободен).
  • **Disk scheduling оптимизирует движение головки HDD.** FCFS хаотичен, SSTF жадный (starvation), SCAN как лифт (справедливый, нет starvation). Для SSD неважен (нет механики), но алгоритмы планирования остаются для fairness и latency.
  • **RAID: trade-off между скоростью, ёмкостью, надёжностью.** RAID 0 - максимум скорости, нулевая защита. RAID 1 - простое зеркало. RAID 5 - баланс (производительность + защита от 1 сбоя). RAID 6 - для больших массивов (защита от 2 сбоев). RAID не заменяет backup!

Связанные темы

Ввод-вывод тесно связан с архитектурой OS и производительностью систем:

  • Файловые системы — FS управляет метаданными и размещением данных на диске. Понимание I/O (блоки, scheduling) необходимо для понимания производительности FS: почему ext4 быстрее ext3, что такое journaling, как работает copy-on-write в Btrfs
  • Виртуальная память — Page faults вызывают дисковый I/O (swap). Swap на HDD убивает производительность (5мс latency), на SSD терпимо. Memory-mapped files (mmap) превращают файловый I/O в работу с памятью - OS управляет загрузкой страниц
  • Планирование процессов — Процесс блокируется на I/O (ждёт диск/сеть) → scheduler переключает на другую задачу. I/O-bound процессы (много I/O) требуют другой стратегии планирования, чем CPU-bound (много вычислений)
  • Сетевое программирование — Сеть - это I/O. Те же принципы: блокирующий I/O (простой, медленный), неблокирующий (select/poll/epoll). Понимание асинхронного I/O необходимо для высокопроизводительных серверов (nginx, Node.js)

Вопросы для размышления

  • Почему базы данных (PostgreSQL, MySQL) так чувствительны к скорости диска? Как понимание I/O поможет оптимизировать производительность БД?
  • При проектировании системы для потокового видео (4K, 60fps): какие методы управления I/O предпочесть? Зачем нужен DMA? Почему RAID 0 может быть полезен?
  • Чем отличается программирование для embedded-систем (микроконтроллеры) от desktop-приложений с точки зрения I/O? Почему на Arduino используют polling, а Linux сервер - epoll?

Связанные уроки

  • os-09-filesystems — Файловая система строится поверх блочного I/O
  • os-04-scheduling — I/O scheduling - тот же класс задач, что CPU scheduling
  • os-18-io-advanced — io_uring, async I/O, vectored I/O - продвинутые техники
  • db-11-query-optimization
Ввод-вывод

0

1

Войти

RAID не заменяет backup

**Частая ошибка:** "У меня RAID 5, данные защищены!" Нет. RAID защищает от **сбоя железа**, но не от: - Случайного удаления файла (удалил → синхронизировалось на все диски) - Вируса-шифровальщика (зашифрует все копии) - Пожара/затопления (все диски погибнут) Правило 3-2-1: **3 копии**, **2 разных носителя**, **1 копия offsite** (в облаке/другом месте).

RAID обеспечивает полную защиту данных, резервное копирование не нужно

RAID защищает только от сбоя железа, но не заменяет backup. Нужны независимые резервные копии

RAID - это **доступность** (availability), а не **backup**. Сценарии, которые RAID не спасёт: 1. **Удаление файла:** Пользователь случайно удалил важную папку → RAID синхронизировал удаление на все диски. Данные потеряны. 2. **Ransomware:** Вирус зашифровал файлы → все копии в RAID тоже зашифрованы. 3. **Физическое повреждение:** Пожар, затопление, кража сервера → все диски уничтожены. 4. **Corruption:** Ошибка в файловой системе перезаписала метаданные → RAID исправно сохранил битые данные. Бэкап должен быть **независимым**, **версионированным** (можно откатиться), **offsite** (физически в другом месте). RAID + backup = настоящая защита.

Почему RAID 5 становится опасным при использовании очень больших дисков (8TB+)?