3.2 Зачем нужна операционная система и как она работает

Ранее в хендбуке мы говорили только об аппаратном уровне, то есть о том, как работает железо: какие компоненты есть у компьютера, как они взаимодействуют, как в них хранятся данные.

В этом параграфе вы узнаете об операционной системе — сущности, которая управляет этим железом, чтобы выполнять команды пользователей. С ней вы уже наверняка знакомы на практике: Windows, Linux, macOS, iOS, Android — всё это примеры операционных систем.

Вот так пойдет наша беседа:

  • Сначала рассмотрим, зачем вообще нужна операционная система.
  • Далее поговорим о том, из каких компонентов состоят операционки.
  • Затем по очереди рассмотрим каждый компонент.

К концу параграфа вы сможете увидеть картину целиком: что делает компьютер в ответ на ваши действия и какие процессы происходят за кулисами.

Поехали!

Что такое операционная система

У каждого из вас есть компьютер или телефон. Представьте себе, что при запуске любой программы вы бы вручную настраивали, какие команды нужно выполнить и передать в процессор, распределяли память для реализации команд, прописывали результат вывода на экран.

То есть отвечали бы за каждую операцию, которая реализуется на аппаратном уровне (его ещё называют «железо» или hardware). Согласитесь, это было бы очень сложно и неудобно.

Поэтому и придумали операционную систему: она делает всю эту работу за вас. Дадим её определение:

Операционная система (ОС) — это набор программного обеспечения (софт или software), которое управляет аппаратным обеспечением компьютера и приложениями, а также распределяет доступ к ресурсам: памяти, процессору, устройствам ввода-вывода и файловому хранилищу.

Таким образом, ОС — это прослойка между пользователем и работой железа, которая позволяет пользователю просто запускать программы и скрывать от его глаз процесс их выполнения.

Схематически иерархию можно изобразить так:

2.1

Как видите, у одной ОС может быть несколько пользователей. Поэтому вы и выбираете своего, прежде чем попасть на рабочий стол. От имени пользователя запускаются различные программы. Когда программам нужны ресурсы от железа (например, оперативная память, доступ к файлам или процессорное время), то они обращаются к операционной системе. А дальше уже операционная система ставит задачи и реализует всю работу с аппаратным обеспечением.

А могут ли в ОС работать несколько пользователей одновременно?

Вполне!

Более того, исторически с компьютерами так и работали — ещё в 1960-х, когда один мощный компьютер с установленной ОС обслуживал десятки пользователей, у которых на рабочем столе стояли терминалы доступа.

Впрочем, многопользовательская архитектура сохранилась: некоторые современные ОС (Linux, macOS, BSD) и Windows Server позволяют нескольким пользователям работать параллельно через удалённые сессии, серверы приложений и облачные сервисы.

Зачем нужна ОС, в общих чертах выяснили. Теперь давайте погружаться в детали.

Из чего состоит операционная система

Представьте: Вася заходит на сайт, нажимает огромную кнопку «Скачать». Он уверен, что скачивает последнюю серию любимого сериала, но на самом деле запускает в браузере код злоумышленника.

Браузер тихо подключается к камере ноутбука Васи и круглосуточно записывает, что он делает перед экраном. Жутко звучит, да? Хорошо, что это невозможно.

Дело в том, что у запущенных программ (а интернет-браузер — это программа) нет прямого доступа к устройствам вроде камеры. А если он им нужен, то они с помощью ОС спрашивают разрешение у пользователя.

Но даже если пользователь разрешил, взаимодействие с железом всё равно происходит через ОС.

Это наводит на мысль, что у разных программ может быть разный вид доступа к элементам компьютера, то есть разный уровень привилегий.

2.1

Уровень привилегий определяет процессор. В современных (x64) определены четыре уровня:

  • Уровень 0. Называется «режим ядра» (Kernel Mode). Это самый привилегированный уровень, в котором у программ есть доступ абсолютно ко всему в компьютере. Если здесь происходит ошибка, то появляется тот самый «синий экран смерти».
  • Уровни 1, 2. Задумывались как доступы к железу для системных сервисов. В современных ОС Windows и Linux не применяются для упрощения архитектуры. Но в то же время остаются на уровне архитектуры процессора.
  • Уровень 3. Это пользовательский, непривилегированный режим (User Mode). На этом уровне работают обычные программы: браузеры, игры, офисные приложения. У них нет прямого доступа к железу и пространству, в котором находится ядро.

Если у нас разный уровень доступа для разных ролей, то должно быть и разное рабочее пространство. Так и есть! Введём ещё две сущности:

  • Пространство пользователя (User Space). Это часть адресного пространства, где работают пользовательские приложения (браузеры, редакторы, игры и т. д.). Здесь код выполняется в User Mode, то есть процессор накладывает ограничения: нет прямого доступа к аппаратуре, можно обращаться к ресурсам только через системные вызовы.
  • Пространство ядра (Kernel Space). Это часть адресного пространства процесса, зарезервированная для работы ядра операционной системы. Здесь выполняются ядро ОС и драйверы устройств, а также хранится доступ к ресурсам оборудования. Доступ к этому пространству возможен только в режиме Kernel Mode.

Вот простая «визуальная» метафора, которая поможет нам всё как следует запомнить. Представьте офис небольшой компании 1990-х.

  • Её основатель может всё. Он находится в Kernel Mode.
  • Её сотрудники... просто работают. Они находятся в User Mode.
  • Сотрудник может ходить только там, где разрешил основатель. Это ограниченная территория User Space.
  • Основатель может ходить везде (пока на него не обратит внимание следствие): даже в секретную комнату за своим кабинетом, где есть баня, бильярдная и стоит сейф с наличкой. Это его рай, это его Kernel Space.

Вы удивитесь, но процессор может играть обе роли поочерёдно и работать то в Kernel Mode, то в User Mode.

  • В первом случае он будет обращаться к устройствам напрямую и ограничений у него нет.
  • Во втором — работать с ограничениями, используя ресурсы User Space.

Эта информация нам ещё пригодится, держите её в уме.

Далее мы подробнее поговорим о пространстве пользователя (User Space), а затем о пространстве ядра (Kernel Space).

Расскажем, как работает каждый элемент, какие идеи лежат в основе, дадим направление, где можно погрузиться глубже, а также подсветим, где можно подсмотреть устройство того или иного элемента у вас на компьютере.

Но сначала важный нюанс: архитектура разных ОС сильно различается. Но базовые функции одни и те же, поэтому далее мы будем опираться на архитектуру ОС систем Linux, потому что у неё более явно выражена структура элементов и их основные функции:

Архитектура ОС систем по типу Linux

Архитектура Windows более многослойная, но использует те же принципы, которые обсудим далее. Давайте погружаться!

Пользовательское пространство (User Space)

Вверху схемы расположено пользовательское пространство, где работают приложения и системные сервисы.

Составные компоненты в User Space

Давайте разберём каждый элемент подробнее.

Приложение (англ. application) — это программа, которая выполняет конкретные задачи для пользователя или системы. Это может быть браузер, текстовый редактор, медиаплеер или серверная служба.

Оболочка (англ. shell) — это особый тип приложения, которое служит посредником между пользователем и операционной системой. Принимает команды (в текстовом или графическом виде), интерпретирует их и запускает другие приложения.

Например, в Windows есть две оболочки:

  • графическая — это Windows Explorer (explorer.exe), который обеспечивает рабочий стол, панель задач, меню «Пуск» и проводник файлов;
  • командная — это командная строка (cmd.exe), которая позволяет работать с системой через текстовые команды: Command Prompt или более современный PowerShell.

Рабочий стол — пример графической оболочки для запуска других программ

Библиотеки (Libraries) — это набор готовых функций и ресурсов, собранных в отдельные файлы (например, .so в Linux или .dll в Windows), которыми могут пользоваться разные приложения.

Они позволяют программистам не писать одно и то же с нуля, а обращаться к уже реализованным возможностям: работать с файлами, сетью, графикой, памятью.

Например, вы хотите прочитать файл. Вы просто берёте функцию read() из библиотеки, а не пишете свою реализацию.


Приложения работают в пространстве пользователя и используют библиотеки. Но если им нужно взаимодействовать с файлами, сетью или оборудованием, то они должны обратиться к ядру.

Например, вы запустили текстовый редактор. Для работы ему нужна память. Чтобы её получить, он обратится к ОС — такие запросы называются системный вызов (System Call). С этого момента работа кода переходит на уровень привилегий Kernel Mode.

И ещё нюанс: получив ресурс, приложение продолжает работать с ним, пока запущено и пока объёма ресурса достаточно. То есть ОС дала память, редактор запустился, вы что-то в нём написали и сохранили. А потом ещё написали и сохранили: он не пойдёт заново за памятью, а будет работать с уже выделенной, пока ему хватает объёма.

Пространство ядра (Kernel Space)

Итак, приложение отправило системный вызов, и мы переходим на территорию пространства ядра. Всё, о чём пойдёт речь далее, относится к этому пространству.

Мы рассмотрим эти элементы по очереди, чтобы не сбивать вас с толку градом терминов. Выше мы сказали, что приложение отправляет системный вызов. Вот с него-то и начнём.

Системный вызов (System Call)

Представьте, что это своего рода «ворота» для входа в ядро операционной системы. Вот его определение:

Системный вызов — инструмент, с помощью которого компьютерная программа просит ядро операционной системы выполнить определённый запрос.

Пример вызова (помимо «дай память»): «Открой файл Х и прочитай его содержимое».

Вызов передаётся в определённую подсистему — в зависимости от категории запроса. Если нужно открыть файл — в файловую систему. Если получить память — в менеджер памяти. И так далее.

Как в МФЦ: вы подаёте документы в одно окошко и описываете суть обращения. А дальше специалист передаёт ваш запрос нужной службе, которая реагирует на него, и вы получаете уведомление о результате.

Вот пример категорий запросов и подсистем для Linux. Такие же категории есть в Windows, но там подсистемы называются иначе.

Системные вызовы в Linux

Более подробную информацию обо всех указанных на картинке вызовах можно посмотреть тут.

Таким образом, для выполнения программ формируется перечень системных вызовов, которые дальше ядро операционной системы обрабатывает следующими подсистемами:

  • Планировщик процессов (Process Scheduler).
  • Межпроцессное взаимодействие (IPC — Inter-Process Communication).
  • Файловая система (File System).
  • Менеджер памяти (Memory Manager).
  • Блок работы с устройствами (I/O Interface, Network Interface и Drivers).

2.1

Рассмотрим работу каждой подсистемы подробнее.

Планировщик процессов (Process Scheduler)

Прежде чем переходить к самому планировщику процессов, давайте для начала введём определение базовой единицы, с которой он работает, — процесса.

Процесс — это программа в состоянии выполнения.

Например, когда мы пишем программу на Python и компилируем её, компилятор создаёт бинарный (машинный) код. Когда бинарный код запускается на выполнение, он становится процессом.

Другой пример: если вы открываете текстовый редактор «Блокнот» в Windows, сначала запускается системный вызов CreateProcess(), и у вас в системе появится процесс notepad.exe, который откроет пустое окно в этой программе.

Если далее внутри программы вы решите открыть другой текстовый файл, то запустится системный вызов команды на открытие и появится ещё один процесс для notepad.exe.

Для описания запущенных процессов в виде, удобном для работы операционной системы, используется структура данных под названием «Блок контроля процессов» (Process Control Block, PCB). Она состоит из следующих элементов:

2.1

  • Состояние процесса (Process State). Возможных состояний четыре: выполняется, ожидает, готов к запуску, завершён.
  • Идентификатор процесса (Process ID). ОС назначает каждому процессу уникальный идентификатор при его создании. Это позволяет различать процессы.
  • Счётчик команд (Program Counter). При выполнении процесса, когда происходит переключение контекста (об этом расскажем ниже), в счётчике команд сохраняется адрес последней инструкции. Это нужно, чтобы процесс мог возобновить выполнение с того места, где был прерван.
  • Регистры процессора (CPU Registers). Значения регистров процессора процесса сохраняются в блоке контроля процессов, чтобы при переключении контекста можно было восстановить состояние процесса.
  • Информация о памяти (Memory Information). Например, базовый адрес или общий объём памяти, выделенный процессу. Это нужно для эффективного управления памятью.
  • Информация для планирования (Process Scheduling Information). Она нужна, чтобы ОС могла принимать решения о порядке выполнения процессов.
  • Учётная информация (Accounting Information). Нужна, чтобы ОС могла отслеживать эффективность работы процессов. Это такие данные, как время использования CPU, объём занятой памяти и т. д.

При этом у ОС одновременно есть десятки или сотни процессов, а CPU — один (или с несколькими ядрами). В один момент на одном ядре может обрабатываться один процесс. Значит, нужно каким-то образом распределить, когда и какой процесс получит время на выполнение.

Тут нам и помогает планировщик процессов. Для этого он:

  1. Читает информацию из блока контроля процессов каждого процесса.
  2. Решает, какой из процессов получит ресурсы процессора.
  3. Переключает контекст. То есть сохраняет состояние выполнения текущего процесса и передаёт ресурсы процессора другому процессу.

Чтобы это было легче визуализировать, представьте, что пишете длинное письмо (процесс A). Вдруг вас отвлёк звонок. Вы закончили предложение (сохранили контекст) и взяли трубку (процесс B). Закончив звонок, возвращаетесь к письму: с того места, на котором остановились.

ОС делает то же самое: приостанавливает один процесс и возвращается к нему позже без потери данных.

В конкретные алгоритмы, как именно планировщик процессов выбирает процесс для передачи в процессор и осуществляет переключение контекста, погружаться не будем. Но если интересно копнуть глубже — можно посмотреть этот материал.

Для просмотра процессов на своём компьютере на Windows можно воспользоваться упомянутым ранее диспетчером задач. Он позволяет взглянуть, какие процессы у вас сейчас запущены и кто больше всего кушает ресурсов процессора (ЦП).

Диспетчер задач, где можно посмотреть перечень процессов и их загрузку (на Windows)

В других ОС есть аналоги. В Linux — GNOME system monitor или KDE System Monitor, в macOS — Activity Monitor.

Межпроцессное взаимодействие (IPC)

Процессам нужно общаться друг с другом, делиться информацией, выстраивать зависимости друг от друга. Потому что если они будут изолированы, то вероятны следующие ситуации:

  1. Невозможность поделиться данными. Например, браузер скачал страницу, но не может передать её процессу рендера для отображения на странице.
  2. Дублирование данных. Например, есть большая база данных. Чтобы работать с данными, каждый процесс будет повторно загружать информацию из базы. Это ненужная нагрузка.
  3. Отсутствие синхронизации. Один процесс не смог бы ждать завершения другого. Например, текстовый редактор не дождался бы принтера, чтобы послать следующую страницу.

Чтобы избежать таких ситуаций, существует межпроцессное взаимодействие.

Межпроцессное взаимодействие (IPC) — это набор механизмов, с помощью которых процессы (программы) могут обмениваться данными и синхронизировать свои действия.

Существует два подхода к реализации IPC:

  • Через разделяемую память (shared memory). Процессы могут использовать разделяемую память как для извлечения информации (например, записи) из другого процесса, так и для передачи определённых данных другим процессам.
  • Через обмен сообщениями (message passing). В этом методе один процесс отправляет сообщение, а другой принимает его.Процессы не делятся памятью, а вместо этого используют системные вызовы (send(), recv() и т. п.). А для передачи применяют разные методы: сокеты, очереди сообщений, семафоры, каналы.

2.1

Межпроцессное взаимодействие подсказывает планировщику процессов, когда нужно переключать контекст. Теперь, если процессу нужны данные для выполнения работы, а их ещё нет, он не кушает лишний ресурс процессора, а перестаёт выполняться и уходит в статус «ожидает». Аналогично если процессор занят другим процессом и пришли данные для более приоритетного процесса — можно быстрее дать ему время на их обработку.

Вроде бы от обмена информации только одни плюсы, но появляется новая проблема, которая может возникнуть при неправильном использовании IPC, — взаимная блокировка. Её ещё называют «дедлок» (англ. deadlock).

Представьте ситуацию, что вы идёте по очень узкому коридору, еле протискиваясь, а вам навстречу идёт другой человек. И вы становитесь друг напротив друга и ждёте, что другой первым уступит дорогу.

Также бывает и с ресурсами. Один процесс захватил ресурс 1 и ждёт ресурс 2. А другой процесс захватил ресурс 2 и ждёт ресурс 1. Никто не двигается, всё — привет, дедлок.

2.1

Чтобы нивелировать этот риск, программисты продумывают специальные алгоритмы, которые обнаруживают и устраняют дедлоки. Сейчас погружаться в эту тему не будем, но если вам любопытно — можно почитать тут.

Напрямую увидеть работу IPC нельзя, это внутренняя механика ядра ОС, она скрыта от наблюдателя. Поэтому в этом разделе красивых скриншотов не будет.

Файловая система (File System)

По традиции начнём с определения.

Файловая система — это часть ядра, используемая ОС для организации файлов и управления ими во внешней памяти. Она определяет правила хранения и организации данных на устройстве хранения, а также доступа к ним.

Эта подсистема выступает в роли моста между ОС и физическим хранилищем (например, HDD или SSD). Она позволяет пользователям и приложениям в организованной и эффективной форме читать файлы, создавать их, обновлять и удалять.

Быстрый факт. Эти операции обозначают одним словом — CRUD. Это аббревиатура от Create, Read, Update, Delete — переводится как «создать, прочитать, обновить, удалить».

Запомните её, она часто используется в компьютерных науках.

Архитектура файловой системы обычно состоит из пяти уровней, каждый из которых отвечает за свой аспект взаимодействия с файлом:

2.1

Разберём эти уровни подробнее.

Приложение пользователя (User Application)

На этом уровне запускаются приложения и формируются системные вызовы, а файлы видятся как имена и пути (C:\notes.txt или /home/user/notes.txt).

Логическая файловая система (Logical File System)

Основная задача этого уровня — решить, есть ли у пользователя права для открытия файла и существует ли такой путь. Файл воспринимается как набор параметров для описания его логики (метаданные):

  • Имена, пути, каталоги.
  • Права доступа, владельцы.
  • Различные атрибуты (время создания, изменения).

Виртуальная файловая система (Virtual File System)

Благодаря VFS приложениям не нужно знать, в каком типе файловой системы хранится файл — NTFS, FAT32, ext4 или другой.

Задача VFS — принять системный вызов от приложения, обработать путь, а затем передать операцию соответствующему драйверу конкретной файловой системы, который уже найдёт и обработает файл на носителе.

Типы файловых систем

Каждая ОС поддерживает определённый набор типов, а многие файловые системы кросс-платформенны.

Вот основные типы файловых систем:

2.1

Скажем пару слов о каждом типе:

  • FAT (File Allocation Table). Старая файловая система, которая использовалась в ранних версиях Windows и других ОС. Можно встретить на флешках, картах памяти, фотоаппаратах.
  • NTFS (New Technology File System). Современная файловая система Windows. Поддерживает такие возможности, как права доступа к файлам и папкам, сжатие и шифрование. Находится на внутренних дисках компьютеров и ноутбуков с Windows.
  • ext (Extended File System). Файловая система, которая обычно используется в Linux. Встречаются на дисках в Linux-серверах.
  • HFS (Hierarchical File System). Файловая система, которая используется в macOS. Встречается на старых MacBook и iMac.
  • APFS (Apple File System). Новая файловая система, представленная Apple для компьютеров Mac и устройств с iOS. Можно увидеть на iPhone с iOS 11+ и MacBook 2018+.

Физическая файловая система (Physical File System)

Это уровень, который отвечает за конкретную реализацию файловой системы на разделе диска.

Здесь определено, как именно организованы данные: где хранятся метаданные, как устроены каталоги, какие блоки или кластеры содержат файл. Физическая файловая система знает внутреннюю структуру носителя (например, ext4, NTFS, FAT32) и сопоставляет логический файл с конкретными физическими блоками на диске.

Блочный уровень (Block Layer)

Это нижний уровень ввода-вывода, который работает напрямую с блочными устройствами: жёсткими дисками (HDD), SSD, флешками. Он абстрагирует операции чтения и записи в виде блоков фиксированного размера (обычно 512 байт или 4 КБ).

Блочный уровень принимает запросы от драйверов файловых систем и передаёт их драйверам устройств, которые преобразуют команды ОС в реальные операции чтения или записи на носителе.


Часть уровней можно рассмотреть подробнее, используя установленные средства операционной системы.

Например, в Windows с помощью проводника можно увидеть пути расположения приложений пользователей, а также метаданные — если открыть свойства файлов. Если хочется поглубже нырнуть в физическую файловую систему, то воспользуйтесь управлением дисками. Там можно подробнее посмотреть информацию об организации данных на них.

В Linux можно воспользоваться файловым менеджером (Nautilus, Dolphin, Thunar и др.) для дисков — GNOME Disks или KDE Partition Manager. В macOS файловый менеджер — Finder, для просмотра информации о дисках — Disk Utility.

Просмотр пути к файлам и их свойства через проводник (Windows)

Просмотр информации о дисках и их параметрах через управление дисками (Windows)

Менеджер памяти (Memory Manager)

Это критически важный аспект операционных систем, который обеспечивает эффективное использование ресурсов памяти компьютера. Он контролирует, как память выделяется и освобождается для процессов, и затрагивает работу всей памяти компьютера. Это важно как для производительности, так и для стабильности системы.

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

2.1

Что именно делает подсистема управления памятью:

  • Выделяет и освобождает память до и после выполнения процесса.
  • Ведёт учёт используемого процессами пространства памяти.
  • Минимизирует проблемы фрагментации. Фрагментация — это ситуация, когда память или дисковое пространство разделяются на множество несмежных мелких участков, из-за чего память между участками становится сложно использовать и она простаивает.
  • Обеспечивает правильное использование основной памяти (RAM, кэши, регистры).
  • Сохраняет целостность данных во время выполнения процесса.

Так как управление памятью работает с процессами, каким-то образом их нужно хранить. С точки зрения данных, процесс в памяти разделён на несколько независимых секций, каждая из которых отвечает за определённую задачу.

Выглядит это следующим образом:

2.1

Коротко прокомментируем:

  • Стек (Stack). Содержит временные данные: параметры функций, адреса возврата и локальные переменные.
  • Свободная область памяти (Unallocated memory) между стеком и кучей в адресном пространстве процесса. Она служит резервом: стек растёт вниз, куча вверх, и эта зона позволяет им динамически расширяться до тех пор, пока они не встретятся.
  • Куча (Heap). Область динамически выделяемой памяти для процесса во время выполнения. Используется для переменных и объектов, размер или срок жизни которых заранее неизвестен.
  • Секция данных (Data). Хранит переменные, которые инициализируются до запуска программы и живут всё время её работы.
  • Текст или секция кода (Text). Содержит исполняемые инструкции программы. Обычно она доступна только для чтения.

Есть множество методов, как можно управлять данными, но в рамках этого параграфа погружаться в них не будем. Для дополнительного изучения можно пройти сюда.

Для управления памятью тоже существуют графические интерфейсы, позволяющие заглянуть за кулисы. В Windows есть мониторинг ресурсов, в Linux — GNOME system monitor или KDE System Monitor, в macOS — Activity Monitor.

Программа мониторинг ресурсов для просмотра использования памяти (Windows)

Блок работы с устройствами

Осталось рассмотреть последнюю подсистему — она отвечает за взаимодействие с устройствами.

Блок работы с устройствами состоит из трёх дополняющих друг друга компонентов: интерфейса ввода-вывода, сетевого интерфейса и драйверов.

2.1

Хотя по своей сути устройства ввода-вывода и сети похожи, исторически они развивались параллельно друг другу и часто на схемах идут отдельно. Связано это с тем, что у них разная природа устройств: ввод-вывод работает в основном с файлами, сеть — с пакетами (подробнее об этом в конце главы).

Что за драйверы?

Это специальные программы, которые помогают операционной системе общаться с железом.
Драйвер знает, какие команды понимает устройство, поэтому помогает переводить запросы ОС в эти команды и обратно. Обычно драйверы пишутся на C или C++, поскольку эти языки позволяют работать как с абстракциями высокого уровня, так и напрямую с памятью и регистрами оборудования.

Глобально блок по работе с устройствами можно разбить на взаимодействие с тремя типами данных:

  • Блочный ввод-вывод(Block I/O Path).
  • Символьный ввод-вывод (Char I/O Path).
  • Сетевой ввод-вывод (Network I/O Path).

Зарисуем на схеме:

2.1

Каждый блок обрабатывает поступающую информацию по своим правилам. Но в целом принцип работы у них одинаковый: есть часть ядра ОС, которая отвечает за распределение запросов к устройствам (I/O path).

Она передаёт формирование этих запросов драйверу. Далее драйвер переводит команды на язык устройства, а процессор их исполняет, обращаясь к устройствам. Вот примеры устройств:

Блочный ввод-вывод (Block I/O Path)

  • Жёсткий диск (HDD)

  • Твердотельный накопитель (SSD, NVMe)

  • Флеш-накопитель (USB flash)

  • CD/DVD, blu-ray-привод

  • SD-карта и другие карты памяти

Символьный ввод-вывод (Char I/O Path)

  • Клавиатура

  • Мышь, тачпад

  • Монитор

  • Принтер

  • Звуковые устройства

  • Камера

Сетевой ввод-вывод (Network I/O Path)

  • Сетевая карта Ethernet (NIC)

  • Bluetooth-адаптер

  • Модемы

  • VPN-интерфейсы

Когда системе нужно что-то от устройства, например напечатать страничку файла, драйвер формирует код, с помощью которого это можно реализовать. А процессор исполняет его и отправляет запросы к устройству.

Давайте рассмотрим несколько примеров для иллюстрации работы потока символов и потока из интернета. Работу с блоками данных разбирали в разделе с файловой системой.

Что произойдёт, если вы на клавиатуре нажмёте клавишу W

  1. Сгенерируется код клавиши (scan code). Информация придёт на чипсет. (можно открыть рядом схему архитектуры компьютера из параграфа 2.4)
  2. Чипсет поднимает прерывание — процессор отвлекается от текущей задачи и делает запрос в драйвер.
  3. Драйвер расшифровывает код клавиши в символ и передаёт в символьный ввод-вывод.
  4. Дальше ОС доставляет событие в пользовательское приложение.
  5. Приложение уже само реагирует на событие и делает необходимое действие. В текстовом редакторе напишется буква w, в игре может произойти определённое действие, зафиксированное за этой клавишей.

Что произойдёт, если вы открываете сайт https://yandex.com/ и по сети получаете пакет данных

  1. Пакет приходит на сетевую карту. Информация передаётся на чипсет.
  2. Чипсет поднимает прерывание — процессор отвлекается от текущей задачи и делает запрос в драйвер.
  3. Пакет передаётся в сетевой ввод-вывод, где он после обработки уходит в User Space, в буфер запущенного ранее процесса браузера.
  4. Приложение получает данные через системные вызовы recv() или read().

Такая базовая логика заложена в работу ОС с устройствами и на Linux, и на Windows, и на macOS. Но вот подходы к реализации у каждой ОС будут свои и будут сильно отличаться друг от друга. Поэтому для дальнейшего погружения надо уже нырять в устройство конкретной ОС.

Чтобы посмотреть, какие устройства и драйверы есть на вашем компьютере, можете на Windows зайти в диспетчер устройств. Там — найти все устройства, подключённые к вашему компьютеру, а также сведения о драйверах к каждому устройству.

Аналог на Linux — Hardinfo, на macOS — System Information.

Диспетчер устройств, для просмотра подключённых устройств и драйверов устройств (Windows)

Что в итоге

Давайте коротко вспомним, что мы узнали из параграфа.

Самое главное — вы познакомились с тем, как операционная система взаимодействует с приложениями и с аппаратным обеспечением. Она управляет ресурсами (CPU, память, устройства ввода-вывода, файловое хранилище), распределяет их между приложениями и обеспечивает удобный интерфейс для работы.

А строится эта работа на нескольких ключевых идеях.

В современных компьютерах есть два уровня привилегий у процессора. Режим ядра (Kernel Mode) даёт полный доступ ко всем ресурсам. Режим пользователя (User Mode) — для работы с приложениями, он ограниченный.

Системные вызовы (System Calls) — это ворота в ядро. Через них приложения запрашивают ресурсы. Эти системные вызовы обрабатывают основные подсистемы ядра ОС.

2.1

Ядро состоит из нескольких подсистем:

  • Планировщик процессов — планирует, какой процесс получит CPU, и переключает контексты.
  • Межпроцессорное взаимодействие — предоставляет механизмы для обмена данными между процессами (shared memory, message passing).
  • Файловая система — организует хранение и доступ к данным на носителях (Logical FS, VFS, Physical FS, Block Layer).
  • Менеджер памяти — выделяет, отслеживает и освобождает память, борется с фрагментацией, хранит структуру процесса (код, стек, данные, куча).
  • Блок работы с устройствами — связывает ядро с устройствами (блочные, символьные, сетевые). Драйверы переводят команды ОС в команды железа.

А драйверы — это программы, которые помогают операционной системе общаться с железом. Драйвер знает, какие команды понимает устройство, поэтому помогает переводить запросы ОС в эти команды и обратно.

Теперь вы знаете, как устроены операционные системы и из каких элементов они состоят. Это большой прогресс: с каждым параграфом остаётся всё меньше места для магии!

А в следующем мы поговорим о сущностях, благодаря которым создаются программы, включая сами операционные системы. Это языки программирования. Мы проследим историю их появления от самых экзотических и коротко расскажем, для каких задач они предназначены.



Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Предыдущий параграф3.1. О чём пойдёт речь в этой главе
Следующий параграф3.3. Как появились языки программирования