Linux: архитектура ядра Linux – общая архитектура системы

Автор: | 11/05/2015

linux_logo

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

Оригинал – на странице Conceptual Architecture of the Linux Kernel.

Более полное описание архитектуры – есть на странице Concrete Architecture of the Linux Kernel.

Обзор системы

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

kernel_arch_1

kernel_arch_2

Операционная система Linux (или – GNU/Linux) состоит из четырёх основных частей:

    1. User applications (пользовательские приложения) – набор пользовательских приложений может быть разным в различных дистрибутивах Linux, но типичные примеры – это приложения обработки текста и веб-браузер;
    2. O/S services (службы операционной системы) – службы, которые обычно считаются частью операционной системы, такие как оконный менеджер, командная строка и т.д. Так же, сюда входит программный интерфейс ядра (компилятор/ы и библиотеки);
    3. Ядро Linux – основная интересующая нас часть; ядро создаёт абстрактный слой и является “посредником” между первыми двумя частями и hardware-частью компьютера;
    4. Hardware controllers (контроллеры оборудования) – подсистема, охватывающая все возможные физические устройства, такие как CPU, устройства памяти, жёсткие диски, сетевые карты – все они являются частью этой подсистемы.

Каждая подсистема может взаимодействовать только с двумя соседними, расположенными непосредственно “выше” и “ниже” её уровня. Кроме того, зависимости между этими подсистемами направлены сверху – вниз: слои расположенные выше – зависят от частей ниже, но части, расположенные ниже – не зависят от частей выше их.

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

Роль ядра

Ядро Linux представляет собой своего рода виртуальную машину для процессов. Процессы работают без всякой информации про оборудование компьютера – ядро абстрагирует весь уровень оборудования в единый совместимый виртуальный интерфейс. Кроме того, ядро реализует многозадачность прозрачно для всех процессов – каждый процесс “думает”, что он является единственным процессом в системе, и имеет полные и эксклюзивные права на память и другие ресурсы оборудования компьютера. Фактически же – ядро выполняет несколько процессов одновременно, и оно ответственно за распределение ресурсов оборудования таким образом, что бы каждый процесс получил достаточный доступ к этим ресурсам.

Обзор структуры и зависимостей подсистем ядра

Ядро Linux состоит из пяти основных подсистем:

  1. Process Scheduler (SCHED) – планировщик процессов, отвечает за контроль над доступом процессов к CPU. Планировщик обеспечивает такое поведения ядра, при котором все процессы имеют справедливый доступ к центральному процессору.
  2. Memory Manager (MM) – менеджер памяти, обеспечивает различным процессам безопасный доступ к основной памяти системы. Кроме того, MM обеспечивает работу виртуальной памяти, которая позволяет процессам использовать больше памяти, чем реально доступно в системе. Выделенная, но неиспользуемая память вытесняется на файловую систему, и при необходимости – возвращается из неё обратно в память (swapping).
  3. Virtual File System(VFS) – виртуальная файловая система, создаёт абстрактный слой, скрывая детали оборудования, предоставляя общий файловый интерфейс для всех устройств. Кроме того, VFS поддерживает несколько форматов файловых систем, которые совместимы с другими операционными системами.
  4. Network Interface (NET) – сетевые интерфейсы, обеспечивает работу с различными сетевыми стандартами и сетевым оборудованием.
  5. Inter-Process Communication (IPC) – межпроцессная подсистема, поддерживающая несколько механизмов для process-to-process связей в единой Linux-системе.

На рисунке ниже изображены связи всех этих подсистем, где линии исходят от зависимых подсистем к подсистемам, от которых они зависят:

Общая структура и связи подсистем ядра Linux

Общая структура и связи подсистем ядра Linux

Тут явно видно, что основной подсистемой является планировщик процессов: все остальные системы зависят от него, так как всем им необходимо приостанавливать и возобновлять выполнение процессов. Как правило, процесс приостанавливается в ожидании каких-либо операций с оборудованием, и возобновляет выполнение, когда операция завершена. Например – когда процесс пытается отправить некое сообщение по сети, сетевой интерфейс может приостановить выполнение процесса, пока сетевое оборудование выполняет отправку сообщения. После того как сообщение отправлено (или – получено сообщение об ошибке) – сетевой интерфейс возобновляет работу процесса, передавая ему код возврата, который указывает на успешное завершение операции, или ошибку её при выполнении. Все остальные подсистемы (memory manager, virtual file system и inter-process communication) так же зависят от планировщика процессов по схожим причинам.

Другие зависимости не так явны, но не менее важны:

  • Планировщик процессов использует менеджер памяти, что бы согласовывать карту памяти для каждого процесса, когда он возобновляет своё выполнение;
  • Подсистема IPC зависит от менеджера памяти для поддержания механизма использования общей памяти; этот механизм позволяет двум процессам получить доступ к области общей памяти, в дополнение к их приватной памяти;
  • Виртуальная файловая система использует сетевые интерфейсы для обеспечения работы NFS (Nework File System), и использует менеджер памяти для обеспечения работы устройства RAM drive;
  • Менеджер памяти использует подсистему виртуальной файловой системы для поддержки swapping-а, и это единственная причина, по которой менеджер памяти зависит от файловой системы; когда процесс запрашивает доступ к участку памяти, который уже был вытеснен на диск (swapped out) – менеджер памяти выполняет запрос к файловой системе, что бы получить обратно данные из хранилища (swap-раздела или swap-файла), а выполнение процесса на это время приостанавливается.

Кроме зависимостей, которые видны явно, все подсистемы ядра зависят  от некоторых общих ресурсов, которые не показаны тут. Сюда входят процедуры, которые используют все подсистемы ядра для выделения (allocate) им и/или высвобождения ими памяти для использования ядром, процедуры для сообщений об ошибках и проблемах, и прочее.

Структуры системы данных

  • Task list: планировщик процессов поддерживает блок данных для активного процесса. Эти блоки данных хранятся в связанных с процессом списке, который называется “task list” (или – структура task_struct);
  • Memory Map: – менеджер памяти хранит карту адресов виртуальной памяти, связанной с адресами памяти физической в основе каждого процесса, а так же хранит дополнительную информацию о получении и замене конкретных страниц памяти; эта информация хранится в структуре данных “process memory-map“, которая в свою очередь хранится в task list планировщика процессов;
  • I-nodes – виртуальная файловая система использует index-nodes (inodes) для представления файлов в логике файловой системы. Структура данных inodes хранит в себе карту адресов блоков, связанную с физическими адресами устройства хранения. inode может совместно использоваться несколькими процессами, если они открывают один и от же файл.
  • Связь данных – все структуры данных хранятся в task list планировщика процессов. Каждый процесс в системе имеет структуру данных, содержащую указатели на его карту памяти, указатели на inode-ы открытых им файлов, а так же – task list содержит указатели на структуры данных, которые представляют собой открытые сетевые соединения, связанные с каждой задачей.