stringtranslate.com

Ядро (операционная система)

Чрезмерное упрощение того, как ядро ​​подключает прикладное программное обеспечение к оборудованию компьютера.

Ядро это компьютерная программа, лежащая в основе операционной системы компьютера , которая, как правило, полностью контролирует все в системе. Ядро также отвечает за предотвращение и смягчение конфликтов между различными процессами. [1] Это часть кода операционной системы, которая всегда находится в памяти [2] и обеспечивает взаимодействие между аппаратными и программными компонентами. Полное ядро ​​контролирует все аппаратные ресурсы (например, ввод-вывод, память, криптография) через драйверы устройств , разрешает конфликты между процессами, касающимися таких ресурсов, и оптимизирует использование общих ресурсов, например, использование ЦП и кэша , файловых систем и сетевых сокетов. В большинстве систем ядро ​​— одна из первых программ, загружаемых при запуске (после загрузчика ). Оно обрабатывает остальную часть запуска, а также память, периферийные устройства и запросы ввода-вывода (I/O) от программного обеспечения , преобразуя их в инструкции по обработке данных для центрального процессора .

Критический код ядра обычно загружается в отдельную область памяти, которая защищена от доступа прикладного программного обеспечения или других менее важных частей операционной системы. Ядро выполняет свои задачи, такие как запуск процессов, управление аппаратными устройствами, такими как жесткий диск , и обработка прерываний, в этом защищенном пространстве ядра . Напротив, прикладные программы, такие как браузеры, текстовые процессоры или аудио- или видеоплееры, используют отдельную область памяти, пользовательское пространство . Такое разделение предотвращает вмешательство пользовательских данных и данных ядра друг в друга и приводит к нестабильности и замедлению [1] , а также предотвращает влияние неисправных приложений на другие приложения или сбой всей операционной системы. Даже в системах, где ядро ​​включено в адресные пространства приложений , защита памяти используется для предотвращения несанкционированного изменения ядра приложениями.

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

Существуют различные конструкции архитектуры ядра. Монолитные ядра работают полностью в одном адресном пространстве с процессором, работающим в режиме супервизора , в основном для скорости. Микроядра запускают большинство, но не все свои службы в пользовательском пространстве, [3] как это делают пользовательские процессы, в основном для устойчивости и модульности . [4] MINIX 3 является ярким примером конструкции микроядра. Ядро Linux является как монолитным, так и модульным, поскольку оно может вставлять и удалять загружаемые модули ядра во время выполнения.

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

Оперативная память

Оперативная память (ОЗУ) используется для хранения как программных инструкций, так и данных. [a] Обычно для выполнения программы в памяти должны присутствовать оба эти элемента. Часто нескольким программам требуется доступ к памяти, часто требуя больше памяти, чем доступно компьютеру. Ядро отвечает за решение о том, какую память может использовать каждый процесс, и определяет, что делать, если памяти недостаточно.

Устройства ввода/вывода

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

Управление ресурсами

Ключевые аспекты, необходимые в управлении ресурсами, — это определение домена выполнения ( адресного пространства ) и механизма защиты, используемого для посредничества в доступе к ресурсам внутри домена. [5] Ядра также предоставляют методы для синхронизации и межпроцессного взаимодействия (IPC). Эти реализации могут быть расположены внутри самого ядра, или ядро ​​может также полагаться на другие процессы, которые оно запускает. Хотя ядро ​​должно предоставлять IPC для предоставления доступа к средствам, предоставляемым друг другом, ядра также должны предоставлять работающим программам метод для выполнения запросов на доступ к этим средствам. Ядро также отвечает за переключение контекста между процессами или потоками.

Управление памятью

Ядро имеет полный доступ к памяти системы и должно разрешать процессам безопасно получать доступ к этой памяти по мере необходимости. Часто первым шагом в этом является виртуальная адресация , обычно достигаемая путем подкачки страниц и/или сегментации . Виртуальная адресация позволяет ядру сделать заданный физический адрес другим адресом, виртуальным адресом. Виртуальные адресные пространства могут быть разными для разных процессов; память, к которой один процесс обращается по определенному (виртуальному) адресу, может отличаться от той, к которой другой процесс обращается по тому же адресу. Это позволяет каждой программе вести себя так, как будто она единственная (кроме ядра) запущенная, и таким образом предотвращает сбои приложений друг друга. [6]

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

Виртуальная адресация также позволяет создавать виртуальные разделы памяти в двух разрозненных областях, одна из которых зарезервирована для ядра ( пространство ядра ), а другая — для приложений ( пространство пользователя ). Процессор не разрешает приложениям обращаться к памяти ядра, что предотвращает повреждение работающего ядра приложением. Это фундаментальное разделение пространства памяти внесло большой вклад в текущие разработки реальных ядер общего назначения и является почти универсальным в таких системах, хотя некоторые исследовательские ядра (например, Singularity ) используют другие подходы.

Управление устройством

Для выполнения полезных функций процессам необходим доступ к периферийным устройствам , подключенным к компьютеру, которые контролируются ядром через драйверы устройств . Драйвер устройства — это компьютерная программа, инкапсулирующая, контролирующая и управляющая аппаратным устройством (через его интерфейс аппаратного/программного обеспечения (HSI)) от имени ОС. Он предоставляет операционной системе API, процедуры и информацию о том, как управлять и взаимодействовать с определенным элементом оборудования. Драйверы устройств являются важной и жизненно важной зависимостью для всех ОС и их приложений. Целью разработки драйвера является абстракция; функция драйвера — преобразовывать предписанные ОС вызовы абстрактных функций (программные вызовы) в вызовы, специфичные для устройства. Теоретически устройство должно работать правильно с подходящим драйвером. Драйверы устройств используются, например, для видеокарт, звуковых карт, принтеров, сканеров, модемов и сетевых карт.

На аппаратном уровне общие абстракции драйверов устройств включают в себя:

А на программном уровне абстракции драйверов устройств включают в себя:

Например, чтобы показать пользователю что-либо на экране, приложение должно сделать запрос к ядру, которое перенаправит запрос своему драйверу дисплея, который затем будет отвечать за фактическую отрисовку символа/пикселя. [6]

Ядро должно поддерживать список доступных устройств. Этот список может быть известен заранее (например, во встроенной системе , где ядро ​​будет переписано, если доступное оборудование изменится), настроен пользователем (обычно на старых ПК и в системах, которые не предназначены для личного использования) или обнаружен операционной системой во время выполнения (обычно называется plug and play ). В системах plug and play диспетчер устройств сначала выполняет сканирование различных периферийных шин , таких как Peripheral Component Interconnect (PCI) или Universal Serial Bus (USB), для обнаружения установленных устройств, а затем ищет соответствующие драйверы.

Поскольку управление устройствами — это тема, сильно зависящая от ОС , эти драйверы обрабатываются по-разному в каждом виде архитектуры ядра, но в каждом случае ядро ​​должно предоставлять ввод -вывод , чтобы позволить драйверам физически получать доступ к своим устройствам через какой-либо порт или область памяти. При проектировании системы управления устройствами необходимо принимать важные решения, поскольку в некоторых проектах доступ может включать переключение контекста , что делает операцию очень интенсивной для ЦП и легко приводит к значительному снижению производительности. [ необходима цитата ]

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

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

Системный вызов — это механизм, который используется прикладной программой для запроса службы у операционной системы. Они используют инструкцию машинного кода , которая заставляет процессор менять режим. Примером может служить переход из режима супервизора в защищенный режим. Здесь операционная система выполняет такие действия, как доступ к аппаратным устройствам или блоку управления памятью . Обычно операционная система предоставляет библиотеку, которая находится между операционной системой и обычными пользовательскими программами. Обычно это библиотека C, такая как Glibc или Windows API. Библиотека обрабатывает низкоуровневые детали передачи информации ядру и переключения в режим супервизора. Системные вызовы включают close, open, read, wait и write.

Чтобы фактически выполнять полезную работу, процесс должен иметь возможность доступа к службам, предоставляемым ядром. Это реализуется по-разному каждым ядром, но большинство из них предоставляют библиотеку C или API , которые, в свою очередь, вызывают соответствующие функции ядра. [7]

Метод вызова функции ядра различается от ядра к ядру. Если используется изоляция памяти, то пользовательский процесс не может вызвать ядро ​​напрямую, поскольку это будет нарушением правил управления доступом процессора. Вот несколько возможностей:

Решения по проектированию ядра

Защита

Важным соображением при проектировании ядра является поддержка, которую оно обеспечивает для защиты от сбоев ( отказоустойчивость ) и от вредоносного поведения ( безопасность ). Эти два аспекта обычно не различаются четко, и принятие этого различия в проектировании ядра приводит к отказу от иерархической структуры для защиты . [5]

Механизмы или политики, предоставляемые ядром, можно классифицировать по нескольким критериям, включая: статические (применяемые во время компиляции ) или динамические (применяемые во время выполнения ); упреждающие или пост-обнаруживающие; в соответствии с принципами защиты, которым они удовлетворяют (например, Деннинг [8] [9] ); поддерживаются ли они оборудованием или основаны на языке; являются ли они в большей степени открытым механизмом или политикой привязки; и многое другое.

Поддержка иерархических доменов защиты [10] обычно реализуется с использованием режимов ЦП .

Многие ядра предоставляют реализацию «возможностей», т. е. объектов, которые предоставляются пользовательскому коду, которые разрешают ограниченный доступ к базовому объекту, управляемому ядром. Типичным примером является обработка файлов: файл — это представление информации, хранящейся на постоянном запоминающем устройстве. Ядро может иметь возможность выполнять множество различных операций, включая чтение, запись, удаление или выполнение, но приложению уровня пользователя может быть разрешено выполнять только некоторые из этих операций (например, ему может быть разрешено только читать файл). Типичная реализация этого заключается в том, что ядро ​​предоставляет объект приложению (обычно так называемый «дескриптор файла»), над которым приложение может затем вызывать операции, действительность которых ядро ​​проверяет во время запроса операции. Такая система может быть расширена для охвата всех объектов, которыми управляет ядро, и, конечно же, объектов, предоставляемых другими пользовательскими приложениями.

Эффективным и простым способом обеспечения аппаратной поддержки возможностей является делегирование блоку управления памятью (MMU) ответственности за проверку прав доступа для каждого доступа к памяти, механизм, называемый адресацией на основе возможностей . [11] Большинство коммерческих компьютерных архитектур не имеют такой поддержки возможностей со стороны MMU.

Альтернативный подход заключается в имитации возможностей с использованием обычно поддерживаемых иерархических доменов. В этом подходе каждый защищенный объект должен находиться в адресном пространстве, к которому приложение не имеет доступа; ядро ​​также поддерживает список возможностей в такой памяти. Когда приложению необходимо получить доступ к объекту, защищенному возможностью, оно выполняет системный вызов, а затем ядро ​​проверяет, предоставляет ли возможность приложения разрешение на выполнение запрошенного действия, и если это разрешено, выполняет доступ для него (либо напрямую, либо путем делегирования запроса другому процессу уровня пользователя). Стоимость производительности переключения адресного пространства ограничивает практичность этого подхода в системах со сложными взаимодействиями между объектами, но он используется в современных операционных системах для объектов, к которым нечасто обращаются или которые не должны выполняться быстро. [12] [13]

Если прошивка не поддерживает механизмы защиты, можно имитировать защиту на более высоком уровне, например, имитируя возможности манипулирования таблицами страниц , но это повлияет на производительность. [14] Однако отсутствие аппаратной поддержки может не быть проблемой для систем, которые решили использовать защиту на основе языка. [15]

Важным решением при проектировании ядра является выбор уровней абстракции, на которых должны быть реализованы механизмы и политики безопасности. Механизмы безопасности ядра играют важную роль в поддержке безопасности на более высоких уровнях. [11] [16] [17] [18] [19]

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

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

По мнению разработчиков Mars Research Group, отсутствие изоляции является одним из основных факторов, подрывающих безопасность ядра. [20] Они предлагают свою структуру изоляции драйверов для защиты, в первую очередь в ядре Linux. [21] [22]

Аппаратная или языковая защита

Типичные компьютерные системы сегодня используют аппаратно-управляемые правила о том, каким программам разрешен доступ к каким данным. Процессор отслеживает выполнение и останавливает программу, которая нарушает правило, например, пользовательский процесс, который пытается записать в память ядра. В системах, в которых отсутствует поддержка возможностей, процессы изолируются друг от друга с помощью отдельных адресных пространств. [23] Вызовы из пользовательских процессов в ядро ​​регулируются, требуя от них использовать один из описанных выше методов системных вызовов.

Альтернативный подход заключается в использовании защиты на основе языка. В системе защиты на основе языка ядро ​​будет разрешать выполнение только кода, созданного доверенным языковым компилятором . Язык может быть разработан таким образом, что программисту будет невозможно дать ему команду сделать что-то, что нарушит требования безопасности. [15]

Преимущества такого подхода включают в себя:

К недостаткам можно отнести:

Примерами систем с языковой защитой являются JX и Singularity от Microsoft .

Процесс сотрудничества

Эдсгер Дейкстра доказал, что с логической точки зрения атомарные операции блокировки и разблокировки, работающие на двоичных семафорах, являются достаточными примитивами для выражения любой функциональности взаимодействия процессов. [24] Однако этот подход обычно считается недостаточным с точки зрения безопасности и эффективности, тогда как подход с передачей сообщений является более гибким. [25] Также доступен ряд других подходов (как более низкого, так и более высокого уровня), при этом многие современные ядра обеспечивают поддержку таких систем, как общая память и удаленные вызовы процедур .

Управление устройствами ввода-вывода

Идея ядра, в котором устройства ввода-вывода обрабатываются единообразно с другими процессами, как параллельные взаимодействующие процессы, была впервые предложена и реализована Бринчем Хансеном (хотя похожие идеи были предложены в 1967 году [26] [27] ). В описании этого Хансеном «общие» процессы называются внутренними процессами , в то время как устройства ввода-вывода называются внешними процессами . [25]

Подобно физической памяти, предоставление приложениям прямого доступа к портам и регистрам контроллера может привести к сбою контроллера или сбою системы. При этом, в зависимости от сложности устройства, некоторые устройства могут стать на удивление сложными для программирования и использовать несколько разных контроллеров. Из-за этого важно предоставить более абстрактный интерфейс для управления устройством. Этот интерфейс обычно выполняется драйвером устройства или уровнем абстракции оборудования. Часто приложениям требуется доступ к этим устройствам. Ядро должно поддерживать список этих устройств, запрашивая их у системы каким-либо образом. Это можно сделать через BIOS или через одну из различных системных шин (например, PCI/PCIE или USB). Используя пример видеодрайвера, когда приложение запрашивает операцию на устройстве, например, отображение символа, ядру необходимо отправить этот запрос текущему активному видеодрайверу. Видеодрайвер, в свою очередь, должен выполнить этот запрос. Это пример межпроцессного взаимодействия (IPC).

Подходы к проектированию на уровне ядра

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

Принцип разделения механизма и политики является существенным различием между философией микро- и монолитных ядер. [28] [29] Здесь механизм является поддержкой, которая позволяет реализовать множество различных политик, в то время как политика является определенным «режимом работы». Пример:

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

В минимальном микроядре включены только некоторые самые основные политики, [29] и его механизмы позволяют тому, что работает поверх ядра (остальная часть операционной системы и другие приложения), решать, какие политики применять (например, управление памятью, высокоуровневое планирование процессов, управление файловой системой и т. д.). [5] [25] Монолитное ядро, напротив, имеет тенденцию включать множество политик, тем самым ограничивая остальную часть системы в использовании их.

Пер Бринч Хансен представил аргументы в пользу разделения механизма и политики. [5] [25] Неспособность должным образом выполнить это разделение является одной из основных причин отсутствия существенных инноваций в существующих операционных системах, [5] проблема, распространенная в компьютерной архитектуре. [30] [31] [32] Монолитный дизайн обусловлен архитектурным подходом к защите «режим ядра»/«пользовательский режим» (технически называемым иерархическими доменами защиты ), который распространен в обычных коммерческих системах; [33] фактически, каждый модуль, нуждающийся в защите, поэтому предпочтительно включать в ядро. [33] Эта связь между монолитным дизайном и «привилегированным режимом» может быть сведена к ключевому вопросу разделения механизма и политики; [5] фактически архитектурный подход «привилегированного режима» объединяет механизм защиты с политиками безопасности, в то время как основной альтернативный архитектурный подход, адресация на основе возможностей , четко различает их, что естественным образом приводит к микроядерному дизайну [5] (см. Разделение защиты и безопасности ).

В то время как монолитные ядра выполняют весь свой код в одном и том же адресном пространстве ( пространстве ядра ), микроядра пытаются запустить большую часть своих служб в пользовательском пространстве, стремясь улучшить удобство обслуживания и модульность кодовой базы. [4] Большинство ядер не вписываются точно в одну из этих категорий, а скорее находятся между этими двумя конструкциями. Они называются гибридными ядрами . Более экзотические конструкции, такие как наноядра и экзоядра, доступны, но редко используются в производственных системах. Например, гипервизор Xen является экзоядром.

Монолитные ядра

Схема монолитного ядра

В монолитном ядре все службы ОС работают вместе с основным потоком ядра, таким образом, также находясь в той же области памяти. Такой подход обеспечивает богатый и мощный доступ к оборудованию. Разработчик UNIX Кен Томпсон заявил, что «по [его] мнению, проще реализовать монолитное ядро». [34] Главными недостатками монолитных ядер являются зависимости между компонентами системы — ошибка в драйвере устройства может привести к сбою всей системы — и тот факт, что большие ядра могут стать очень сложными в обслуживании; Томпсон также заявил, что «[монолитному ядру] также проще превратиться в беспорядок в спешке по мере его изменения». [34]

Монолитные ядра, которые традиционно использовались в операционных системах типа Unix, содержат все основные функции операционной системы и драйверы устройств. Монолитное ядро ​​— это одна программа, которая содержит весь код, необходимый для выполнения каждой задачи, связанной с ядром. Каждая часть, к которой должно обращаться большинство программ, которые не могут быть помещены в библиотеку, находится в пространстве ядра: драйверы устройств, планировщик, обработка памяти, файловые системы и сетевые стеки. Множество системных вызовов предоставляется приложениям, чтобы позволить им получить доступ ко всем этим службам. Монолитное ядро, хотя изначально загружено подсистемами, которые могут не понадобиться, можно настроить до такой степени, что оно будет таким же быстрым или быстрее, чем то, которое было специально разработано для оборудования, хотя и более релевантным в общем смысле.

Современные монолитные ядра, такие как ядро ​​Linux , ядро ​​FreeBSD , ядро ​​AIX , ядро ​​HP-UX и ядро ​​Solaris , все из которых относятся к категории Unix-подобных операционных систем, поддерживают загружаемые модули ядра , что позволяет загружать модули в ядро ​​во время выполнения, что позволяет легко расширять возможности ядра по мере необходимости, одновременно помогая минимизировать объем кода, работающего в пространстве ядра.

Большая часть работы в монолитном ядре выполняется через системные вызовы. Это интерфейсы, обычно хранящиеся в табличной структуре, которые обращаются к некоторой подсистеме внутри ядра, такой как дисковые операции. По сути, вызовы производятся внутри программ, и проверенная копия запроса передается через системный вызов. Следовательно, далеко ходить не надо. Монолитное ядро ​​Linux можно сделать чрезвычайно маленьким не только из-за его способности динамически загружать модули, но и из-за его простоты настройки. Фактически, есть некоторые версии, которые достаточно малы, чтобы поместиться вместе с большим количеством утилит и других программ на одном гибком диске и при этом обеспечить полностью функциональную операционную систему (одной из самых популярных является muLinux ). Эта возможность миниатюризации ядра также привела к быстрому росту использования Linux во встраиваемых системах .

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

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

Микроядра

Микроядро (также сокращенно μK или uK) — это термин, описывающий подход к проектированию операционной системы, при котором функциональность системы перемещается из традиционного «ядра» в набор «серверов», которые взаимодействуют через «минимальное» ядро, оставляя как можно меньше в «системном пространстве» и как можно больше в «пространстве пользователя». Микроядро, разработанное для определенной платформы или устройства, всегда будет иметь только то, что ему нужно для работы. Подход микроядра состоит в определении простой абстракции над оборудованием с набором примитивов или системных вызовов для реализации минимальных служб ОС, таких как управление памятью , многозадачность и межпроцессное взаимодействие . Другие службы, включая те, которые обычно предоставляются ядром, такие как сетевые , реализуются в программах пользовательского пространства, называемых серверами . Микроядра проще поддерживать, чем монолитные ядра, но большое количество системных вызовов и переключений контекста может замедлить работу системы, поскольку они обычно генерируют больше накладных расходов, чем простые вызовы функций.

Только те части, которые действительно требуют нахождения в привилегированном режиме, находятся в пространстве ядра: IPC (межпроцессное взаимодействие), базовый планировщик или примитивы планирования, базовая обработка памяти, базовые примитивы ввода-вывода. Многие критические части теперь работают в пространстве пользователя: полный планировщик, обработка памяти, файловые системы и сетевые стеки. Микроядра были изобретены как реакция на традиционную «монолитную» конструкцию ядра, в которой вся системная функциональность была помещена в одну статическую программу, работающую в специальном «системном» режиме процессора. В микроядре выполняются только самые фундаментальные задачи, такие как возможность доступа к некоторым (не обязательно всем) аппаратным средствам, управление памятью и координация передачи сообщений между процессами. Некоторые системы, использующие микроядра, — это QNX и HURD. В случае QNX и Hurd пользовательские сеансы могут быть полными снимками самой системы или представлениями, как их называют. Сама суть архитектуры микроядра иллюстрирует некоторые из ее преимуществ:

Большинство микроядер используют систему передачи сообщений для обработки запросов от одного сервера к другому. Система передачи сообщений обычно работает на основе порта с микроядром. Например, если отправляется запрос на большую память, порт открывается с микроядром и запрос отправляется через него. Попав в микроядро, шаги похожи на системные вызовы. Обоснованием было то, что это привнесет модульность в архитектуру системы, что повлечет за собой более чистую систему, более легкую для отладки или динамического изменения, настраиваемую под потребности пользователей и более производительную. Они являются частью операционных систем, таких как GNU Hurd , MINIX , MkLinux , QNX и Redox OS . Хотя микроядра сами по себе очень малы, в сочетании со всем необходимым вспомогательным кодом они, по сути, часто больше монолитных ядер. Сторонники монолитных ядер также отмечают, что двухуровневая структура микроядерных систем, в которой большая часть операционной системы не взаимодействует напрямую с оборудованием, создает немалые затраты с точки зрения эффективности системы. Эти типы ядер обычно предоставляют только минимальные услуги, такие как определение адресных пространств памяти, межпроцессное взаимодействие (IPC) и управление процессами. Другие функции, такие как запуск аппаратных процессов, не обрабатываются напрямую микроядрами. Сторонники микроядер отмечают, что эти монолитные ядра имеют тот недостаток, что ошибка в ядре может привести к сбою всей системы. Однако с микроядром, если процесс ядра выходит из строя, все еще возможно предотвратить сбой системы в целом, просто перезапустив службу, которая вызвала ошибку.

Другие службы, предоставляемые ядром, такие как сетевые, реализованы в программах пользовательского пространства, называемых серверами . Серверы позволяют изменять операционную систему, просто запуская и останавливая программы. Например, для машины без сетевой поддержки сетевой сервер не запускается. Задача перемещения в ядро ​​и из него для перемещения данных между различными приложениями и серверами создает накладные расходы, которые пагубно влияют на эффективность микроядер по сравнению с монолитными ядрами.

Однако недостатки микроядра существуют. Вот некоторые из них:

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

Микроядро позволяет реализовать оставшуюся часть операционной системы как обычную прикладную программу, написанную на языке высокого уровня , и использовать различные операционные системы поверх того же неизмененного ядра. Также возможно динамически переключаться между операционными системами и иметь более одной активной одновременно. [25]

Монолитные ядра против микроядер

По мере роста ядра компьютера растут и размер и уязвимость его доверенной вычислительной базы ; и, помимо снижения безопасности, существует проблема увеличения объема памяти . Это смягчается в некоторой степени путем совершенствования системы виртуальной памяти , но не все компьютерные архитектуры поддерживают виртуальную память. [b] Чтобы уменьшить объем памяти ядра, необходимо выполнить обширное редактирование для тщательного удаления ненужного кода, что может быть очень сложно из-за неочевидных взаимозависимостей между частями ядра с миллионами строк кода.

К началу 1990-х годов из-за различных недостатков монолитных ядер по сравнению с микроядрами монолитные ядра считались устаревшими практически всеми исследователями операционных систем. [ требуется ссылка ] В результате проектирование Linux как монолитного ядра, а не микроядра стало темой знаменитого спора между Линусом Торвальдсом и Эндрю Таненбаумом . [35] Аргументы, представленные в дебатах Таненбаума и Торвальдса , имеют свои достоинства с обеих сторон .

Производительность

Монолитные ядра спроектированы так, чтобы весь их код находился в одном адресном пространстве ( пространстве ядра ), что, по мнению некоторых разработчиков, необходимо для повышения производительности системы. [36] Некоторые разработчики также утверждают, что монолитные системы чрезвычайно эффективны, если они хорошо написаны. [36] Монолитная модель имеет тенденцию быть более эффективной [37] за счет использования общей памяти ядра, а не более медленной системы IPC микроядерных конструкций, которая обычно основана на передаче сообщений . [ требуется ссылка ]

The performance of microkernels was poor in both the 1980s and early 1990s.[38][39] However, studies that empirically measured the performance of these microkernels did not analyze the reasons of such inefficiency.[38] The explanations of this data were left to "folklore", with the assumption that they were due to the increased frequency of switches from "kernel-mode" to "user-mode", to the increased frequency of inter-process communication and to the increased frequency of context switches.[38]

In fact, as guessed in 1995, the reasons for the poor performance of microkernels might as well have been: (1) an actual inefficiency of the whole microkernel approach, (2) the particular concepts implemented in those microkernels, and (3) the particular implementation of those concepts. Therefore it remained to be studied if the solution to build an efficient microkernel was, unlike previous attempts, to apply the correct construction techniques.[38]

On the other end, the hierarchical protection domains architecture that leads to the design of a monolithic kernel[33] has a significant performance drawback each time there's an interaction between different levels of protection (i.e., when a process has to manipulate a data structure both in "user mode" and "supervisor mode"), since this requires message copying by value.[40]

The hybrid kernel approach combines the speed and simpler design of a monolithic kernel with the modularity and execution safety of a microkernel

Hybrid (or modular) kernels

Hybrid kernels are used in most commercial operating systems such as Microsoft Windows NT 3.1, NT 3.5, NT 3.51, NT 4.0, 2000, XP, Vista, 7, 8, 8.1 and 10. Apple's own macOS uses a hybrid kernel called XNU, which is based upon code from OSF/1's Mach kernel (OSFMK 7.3)[41] and FreeBSD's monolithic kernel. Hybrid kernels are similar to microkernels, except they include some additional code in kernel-space to increase performance. These kernels represent a compromise that was implemented by some developers to accommodate the major advantages of both monolithic and microkernels. These types of kernels are extensions of microkernels with some properties of monolithic kernels. Unlike monolithic kernels, these types of kernels are unable to load modules at runtime on their own.[citation needed] This implies running some services (such as the network stack or the filesystem) in kernel space to reduce the performance overhead of a traditional microkernel, but still running kernel code (such as device drivers) as servers in user space.

Many traditionally monolithic kernels are now at least adding (or else using) the module capability. The most well known of these kernels is the Linux kernel. The modular kernel essentially can have parts of it that are built into the core kernel binary or binaries that load into memory on demand. A code tainted module has the potential to destabilize a running kernel. It is possible to write a driver for a microkernel in a completely separate memory space and test it before "going" live. When a kernel module is loaded, it accesses the monolithic portion's memory space by adding to it what it needs, therefore, opening the doorway to possible pollution. A few advantages to the modular (or) Hybrid kernel are:

Modules, generally, communicate with the kernel using a module interface of some sort. The interface is generalized (although particular to a given operating system) so it is not always possible to use modules. Often the device drivers may need more flexibility than the module interface affords. Essentially, it is two system calls and often the safety checks that only have to be done once in the monolithic kernel now may be done twice. Some of the disadvantages of the modular approach are:

Nanokernels

A nanokernel delegates virtually all services – including even the most basic ones like interrupt controllers or the timer – to device drivers to make the kernel memory requirement even smaller than a traditional microkernel.[42]

Exokernels

Exokernels are a still-experimental approach to operating system design. They differ from other types of kernels in limiting their functionality to the protection and multiplexing of the raw hardware, providing no hardware abstractions on top of which to develop applications. This separation of hardware protection from hardware management enables application developers to determine how to make the most efficient use of the available hardware for each specific program.

Exokernels in themselves are extremely small. However, they are accompanied by library operating systems (see also unikernel), providing application developers with the functionalities of a conventional operating system. This comes down to every user writing their own rest-of-the kernel from near scratch, which is a very-risky, complex and quite a daunting assignment - particularly in a time-constrained production-oriented environment, which is why exokernels have never caught on.[citation needed] A major advantage of exokernel-based systems is that they can incorporate multiple library operating systems, each exporting a different API, for example one for high level UI development and one for real-time control.

Multikernels

A multikernel operating system treats a multi-core machine as a network of independent cores, as if it were a distributed system. It does not assume shared memory but rather implements inter-process communications as message passing.[43][44] Barrelfish was the first operating system to be described as a multikernel.

History of kernel development

Early operating system kernels

Strictly speaking, an operating system (and thus, a kernel) is not required to run a computer. Programs can be directly loaded and executed on the "bare metal" machine, provided that the authors of those programs are willing to work without any hardware abstraction or operating system support. Most early computers operated this way during the 1950s and early 1960s, which were reset and reloaded between the execution of different programs. Eventually, small ancillary programs such as program loaders and debuggers were left in memory between runs, or loaded from ROM. As these were developed, they formed the basis of what became early operating system kernels. The "bare metal" approach is still used today on some video game consoles and embedded systems,[45] but in general, newer computers use modern operating systems and kernels.

In 1969, the RC 4000 Multiprogramming System introduced the system design philosophy of a small nucleus "upon which operating systems for different purposes could be built in an orderly manner",[46] what would be called the microkernel approach.

Time-sharing operating systems

In the decade preceding Unix, computers had grown enormously in power – to the point where computer operators were looking for new ways to get people to use their spare time on their machines. One of the major developments during this era was time-sharing, whereby a number of users would get small slices of computer time, at a rate at which it appeared they were each connected to their own, slower, machine.[47]

The development of time-sharing systems led to a number of problems. One was that users, particularly at universities where the systems were being developed, seemed to want to hack the system to get more CPU time. For this reason, security and access control became a major focus of the Multics project in 1965.[48] Another ongoing issue was properly handling computing resources: users spent most of their time staring at the terminal and thinking about what to input instead of actually using the resources of the computer, and a time-sharing system should give the CPU time to an active user during these periods. Finally, the systems typically offered a memory hierarchy several layers deep, and partitioning this expensive resource led to major developments in virtual memory systems.

Amiga

The Commodore Amiga was released in 1985, and was among the first – and certainly most successful – home computers to feature an advanced kernel architecture. The AmigaOS kernel's executive component, exec.library, uses a microkernel message-passing design, but there are other kernel components, like graphics.library, that have direct access to the hardware. There is no memory protection, and the kernel is almost always running in user mode. Only special actions are executed in kernel mode, and user-mode applications can ask the operating system to execute their code in kernel mode.

Unix

A diagram of the predecessor/successor family relationship for Unix-like systems

During the design phase of Unix, programmers decided to model every high-level device as a file, because they believed the purpose of computation was data transformation.[49]

For instance, printers were represented as a "file" at a known location – when data was copied to the file, it printed out. Other systems, to provide a similar functionality, tended to virtualize devices at a lower level – that is, both devices and files would be instances of some lower level concept. Virtualizing the system at the file level allowed users to manipulate the entire system using their existing file management utilities and concepts, dramatically simplifying operation. As an extension of the same paradigm, Unix allows programmers to manipulate files using a series of small programs, using the concept of pipes, which allowed users to complete operations in stages, feeding a file through a chain of single-purpose tools. Although the end result was the same, using smaller programs in this way dramatically increased flexibility as well as ease of development and use, allowing the user to modify their workflow by adding or removing a program from the chain.

In the Unix model, the operating system consists of two parts: first, the huge collection of utility programs that drive most operations; second, the kernel that runs the programs.[49] Under Unix, from a programming standpoint, the distinction between the two is fairly thin; the kernel is a program, running in supervisor mode,[c] that acts as a program loader and supervisor for the small utility programs making up the rest of the system, and to provide locking and I/O services for these programs; beyond that, the kernel didn't intervene at all in user space.

Over the years the computing model changed, and Unix's treatment of everything as a file or byte stream no longer was as universally applicable as it was before. Although a terminal could be treated as a file or a byte stream, which is printed to or read from, the same did not seem to be true for a graphical user interface. Networking posed another problem. Even if network communication can be compared to file access, the low-level packet-oriented architecture dealt with discrete chunks of data and not with whole files. As the capability of computers grew, Unix became increasingly cluttered with code. It is also because the modularity of the Unix kernel is extensively scalable.[50] While kernels might have had 100,000 lines of code in the seventies and eighties, kernels like Linux, of modern Unix successors like GNU, have more than 13 million lines.[51]

Modern Unix-derivatives are generally based on module-loading monolithic kernels. Examples of this are the Linux kernel in the many distributions of GNU, IBM AIX, as well as the Berkeley Software Distribution variant kernels such as FreeBSD, DragonFly BSD, OpenBSD, NetBSD, and macOS. Apart from these alternatives, amateur developers maintain an active operating system development community, populated by self-written hobby kernels which mostly end up sharing many features with Linux, FreeBSD, DragonflyBSD, OpenBSD or NetBSD kernels and/or being compatible with them.[52]

Classic Mac OS and macOS

Apple first launched its classic Mac OS in 1984, bundled with its Macintosh personal computer. Apple moved to a nanokernel design in Mac OS 8.6. Against this, the modern macOS (originally named Mac OS X) is based on Darwin, which uses a hybrid kernel called XNU, which was created by combining the 4.3BSD kernel and the Mach kernel.[53]

Microsoft Windows

Microsoft Windows was first released in 1985 as an add-on to MS-DOS. Because of its dependence on another operating system, initial releases of Windows, prior to Windows 95, were considered an operating environment (not to be confused with an operating system). This product line continued to evolve through the 1980s and 1990s, with the Windows 9x series adding 32-bit addressing and pre-emptive multitasking; but ended with the release of Windows Me in 2000.

Microsoft also developed Windows NT, an operating system with a very similar interface, but intended for high-end and business users. This line started with the release of Windows NT 3.1 in 1993, and was introduced to general users with the release of Windows XP in October 2001—replacing Windows 9x with a completely different, much more sophisticated operating system. This is the line that continues with Windows 11.

The architecture of Windows NT's kernel is considered a hybrid kernel because the kernel itself contains tasks such as the Window Manager and the IPC Managers, with a client/server layered subsystem model.[54] It was designed as a modified microkernel, as the Windows NT kernel was influenced by the Mach microkernel but does not meet all of the criteria of a pure microkernel.

IBM Supervisor

Supervisory program or supervisor is a computer program, usually part of an operating system, that controls the execution of other routines and regulates work scheduling, input/output operations, error actions, and similar functions and regulates the flow of work in a data processing system.

Historically, this term was essentially associated with IBM's line of mainframe operating systems starting with OS/360. In other operating systems, the supervisor is generally called the kernel.

In the 1970s, IBM further abstracted the supervisor state from the hardware, resulting in a hypervisor that enabled full virtualization, i.e. the capacity to run multiple operating systems on the same machine totally independently from each other. Hence the first such system was called Virtual Machine or VM.

Development of microkernels

Although Mach, developed by Richard Rashid at Carnegie Mellon University, is the best-known general-purpose microkernel, other microkernels have been developed with more specific aims. The L4 microkernel family (mainly the L3 and the L4 kernel) was created to demonstrate that microkernels are not necessarily slow.[55] Newer implementations such as Fiasco and Pistachio are able to run Linux next to other L4 processes in separate address spaces.[56][57]

Additionally, QNX is a microkernel which is principally used in embedded systems,[58] and the open-source software MINIX, while originally created for educational purposes, is now focused on being a highly reliable and self-healing microkernel OS.

See also

Notes

  1. ^ It may depend on the Computer architecture
  2. ^ Virtual addressing is most commonly achieved through a built-in memory management unit.
  3. ^ The highest privilege level has various names throughout different architectures, such as supervisor mode, kernel mode, CPL0, DPL0, ring 0, etc. See Protection ring for more information.

References

  1. ^ a b "Kernel". Linfo. Bellevue Linux Users Group. Archived from the original on 8 December 2006. Retrieved 15 September 2016.
  2. ^ Randal E. Bryant; David R. O'Hallaron (2016). Computer Systems: A Programmer's Perspective (Third ed.). Pearson. p. 17. ISBN 978-0-13-409266-9.
  3. ^ cf. Daemon (computing)
  4. ^ a b Roch 2004
  5. ^ a b c d e f g Wulf 1974 pp.337–345
  6. ^ a b Silberschatz 1991
  7. ^ Tanenbaum, Andrew S. (2008). Modern Operating Systems (3rd ed.). Prentice Hall. pp. 50–51. ISBN 978-0-13-600663-3. . . . nearly all system calls [are] invoked from C programs by calling a library procedure . . . The library procedure . . . executes a TRAP instruction to switch from user mode to kernel mode and start execution . . .
  8. ^ Denning 1976
  9. ^ Swift 2005, p.29 quote: "isolation, resource control, decision verification (checking), and error recovery."
  10. ^ Schroeder 72
  11. ^ a b Linden 76
  12. ^ Eranian, Stephane; Mosberger, David (2002). "Virtual Memory in the IA-64 Linux Kernel". IA-64 Linux Kernel: Design and Implementation. Prentice Hall PTR. ISBN 978-0-13-061014-0.
  13. ^ Silberschatz & Galvin, Operating System Concepts, 4th ed, pp. 445 & 446
  14. ^ Hoch, Charles; J. C. Browne (July 1980). "An implementation of capabilities on the PDP-11/45". ACM SIGOPS Operating Systems Review. 14 (3): 22–32. doi:10.1145/850697.850701. S2CID 17487360.
  15. ^ a b Schneider, Fred B.; Morrissett, Greg; Harper, Robert. "A Language-Based Approach to Security" (PDF). Archived (PDF) from the original on 2018-12-22.
  16. ^ a b c Loscocco, P. A.; Smalley, S. D.; Muckelbauer, P. A.; Taylor, R. C.; Turner, S. J.; Farrell, J. F. (October 1998). "The Inevitability of Failure: The Flawed Assumption of Security in Modern Computing Environments". Proceedings of the 21st National Information Systems Security Conference. pp. 303–314. Archived from the original on 2007-06-21.
  17. ^ Lepreau, Jay; Ford, Bryan; Hibler, Mike (1996). "The persistent relevance of the local operating system to global applications". Proceedings of the 7th workshop on ACM SIGOPS European workshop Systems support for worldwide applications - EW 7. pp. 133–140. doi:10.1145/504450.504477. ISBN 978-1-4503-7339-5. S2CID 10027108.
  18. ^ Anderson, J. (October 1972). Computer Security Technology Planning Study (PDF) (Report). Vol. II. Air Force Electronic Systems Division. ESD-TR-73-51, Vol. II. Archived (PDF) from the original on 2011-07-21.
  19. ^ Jerry H. Saltzer; Mike D. Schroeder (September 1975). "The protection of information in computer systems". Proceedings of the IEEE. 63 (9): 1278–1308. CiteSeerX 10.1.1.126.9257. doi:10.1109/PROC.1975.9939. S2CID 269166. Archived from the original on 2021-03-08. Retrieved 2007-07-15.
  20. ^ "Fine-grained kernel isolation". mars-research.github.io. Retrieved 15 September 2022.
  21. ^ Fetzer, Mary. "Automatic device driver isolation protects against bugs in operating systems". Pennsylvania State University via techxplore.com. Retrieved 15 September 2022.
  22. ^ Huang, Yongzhe; Narayanan, Vikram; Detweiler, David; Huang, Kaiming; Tan, Gang; Jaeger, Trent; Burtsev, Anton (2022). "KSplit: Automating Device Driver Isolation" (PDF). Retrieved 20 December 2023.
  23. ^ Jonathan S. Shapiro; Jonathan M. Smith; David J. Farber (1999). "EROS". ACM Sigops Operating Systems Review. 33 (5): 170–185. doi:10.1145/319344.319163.
  24. ^ Dijkstra, E. W. Cooperating Sequential Processes. Math. Dep., Technological U., Eindhoven, Sept. 1965.
  25. ^ a b c d e Brinch Hansen 70 pp.238–241
  26. ^ Harrison, M. C.; Schwartz, J. T. (1967). "SHARER, a time sharing system for the CDC 6600". Communications of the ACM. 10 (10): 659–665. doi:10.1145/363717.363778. S2CID 14550794.
  27. ^ Huxtable, D. H. R.; Warwick, M. T. (1967). "Dynamic Supervisors - their design and construction". Proceedings of the ACM symposium on Operating System Principles - SOSP '67. pp. 11.1–11.17. doi:10.1145/800001.811675. ISBN 978-1-4503-7370-8. S2CID 17709902. Retrieved 2023-12-20.
  28. ^ Baiardi 1988
  29. ^ a b Levin 75
  30. ^ Denning 1980
  31. ^ Nehmer, Jürgen (1991). "The Immortality of Operating Systems, or: Is Research in Operating Systems still Justified?". Lecture Notes In Computer Science; Vol. 563. Proceedings of the International Workshop on Operating Systems of the 90s and Beyond. pp. 77–83. doi:10.1007/BFb0024528. ISBN 3-540-54987-0. The past 25 years have shown that research on operating system architecture had a minor effect on existing main stream [sic] systems.
  32. ^ Levy 84, p.1 quote: "Although the complexity of computer applications increases yearly, the underlying hardware architecture for applications has remained unchanged for decades."
  33. ^ a b c Levy 84, p.1 quote: "Conventional architectures support a single privileged mode of operation. This structure leads to monolithic design; any module needing protection must be part of the single operating system kernel. If, instead, any module could execute within a protected domain, systems could be built as a collection of independent modules extensible by any user."
  34. ^ a b "Open Sources: Voices from the Open Source Revolution". 1-56592-582-3. 29 March 1999. Archived from the original on 1 February 2020. Retrieved 24 March 2019.
  35. ^ Recordings of the debate between Torvalds and Tanenbaum can be found at dina.dk Archived 2012-10-03 at the Wayback Machine, groups.google.com Archived 2013-05-26 at the Wayback Machine, oreilly.com Archived 2014-09-21 at the Wayback Machine and Andrew Tanenbaum's website Archived 2015-08-05 at the Wayback Machine
  36. ^ a b Matthew Russell. "What Is Darwin (and How It Powers Mac OS X)". O'Reilly Media. Archived from the original on 2007-12-08. Retrieved 2008-12-09. The tightly coupled nature of a monolithic kernel allows it to make very efficient use of the underlying hardware [...] Microkernels, on the other hand, run a lot more of the core processes in userland. [...] Unfortunately, these benefits come at the cost of the microkernel having to pass a lot of information in and out of the kernel space through a process known as a context switch. Context switches introduce considerable overhead and therefore result in a performance penalty.
  37. ^ "Operating Systems/Kernel Models - Wikiversity". en.wikiversity.org. Archived from the original on 2014-12-18. Retrieved 2014-12-18.
  38. ^ a b c d Liedtke 95
  39. ^ Härtig 97
  40. ^ Hansen 73, section 7.3 p.233 "interactions between different levels of protection require transmission of messages by value"
  41. ^ Magee, Jim. WWDC 2000 Session 106 – Mac OS X: Kernel. 14 minutes in. Archived from the original on 2021-10-30.
  42. ^ "KeyKOS Nanokernel Architecture". Archived from the original on 2011-06-21.
  43. ^ Baumann, Andrew; Barham, Paul; Dagand, Pierre-Evariste; Harris, Tim; Isaacs, Rebecca; Peter, Simon; Roscoe, Timothy; Schüpbach, Adrian; Singhania, Akhilesh (2009). The Multikernel: a new OS architecture for scalable multicore systems (PDF). 22nd Symposium on Operating Systems Principles.
  44. ^ "The Barrelfish operating system".
  45. ^ Ball: Embedded Microprocessor Designs, p. 129
  46. ^ Hansen 2001 (os), pp.17–18
  47. ^ "BSTJ version of C.ACM Unix paper". bell-labs.com. Archived from the original on 2005-12-30. Retrieved 2006-08-17.
  48. ^ Corbató, F. J.; Vissotsky, V. A. Introduction and Overview of the Multics System. 1965 Fall Joint Computer Conference. Archived from the original on 2011-07-09.
  49. ^ a b "The Single Unix Specification". The Open Group. Archived from the original on 2016-10-04. Retrieved 2016-09-29.
  50. ^ "Unix's Revenge". asymco.com. 29 September 2010. Archived from the original on 9 November 2010. Retrieved 2 October 2010.
  51. ^ Wheeler, David A. (October 12, 2004). "Linux Kernel 2.6: It's Worth More!".
  52. ^ This community mostly gathers at Bona Fide OS Development Archived 2022-01-17 at the Wayback Machine, The Mega-Tokyo Message Board Archived 2022-01-25 at the Wayback Machine and other operating system enthusiast web sites.
  53. ^ Singh, Amit (December 2003). "XNU: The Kernel". Archived from the original on 2011-08-12.
  54. ^ "Windows - Official Site for Microsoft Windows 10 Home & Pro OS, laptops, PCs, tablets & more". windows.com. Archived from the original on 2011-08-20. Retrieved 2019-03-24.
  55. ^ "The L4 microkernel family - Overview". os.inf.tu-dresden.de. Archived from the original on 2006-08-21. Retrieved 2006-08-11.
  56. ^ "The Fiasco microkernel - Overview". os.inf.tu-dresden.de. Archived from the original on 2006-06-16. Retrieved 2006-07-10.
  57. ^ Zoller (inaktiv), Heinz (7 December 2013). "L4Ka - L4Ka Project". www.l4ka.org. Archived from the original on 19 April 2001. Retrieved 24 March 2019.
  58. ^ "QNX Operating Systems". blackberry.qnx.com. Archived from the original on 2019-03-24. Retrieved 2019-03-24.

Sources

Further reading

External links