что такое пространство ядра операционной системы
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
Ядро (Операционные Системы)
Все операции, связанные с процессами, выполняются под управлением той части операционной системы, которая называется ядром. Ядро представляет собой лишь небольшую часть кода операционной системы в целом, однако оно относится к числу наиболее интенсивно используемых компонент системы. По этой причине ядро обычно резидентно размещается в основной памяти, в то время как другие части операционной системы перемещаются во внешнюю память и обратно по мере необходимости. Одной из самых важных функций, реализованных в ядре, является обработка прерываний. В больших многоабонентских системах в процессор поступает постоянный поток прерываний. Быстрая реакция на эти прерывания играет весьма важную роль с точки зрения полноты использования ресурсов системы и обеспечения приемлемых значений времени ответа для пользователей, работающих в диалоговом режиме.
Когда ядро обрабатывает текущее прерывание, оно запрещает другие прерывания и разрешает их снова только после завершения обработки текущего прерывания. При постоянном потоке прерываний может сложиться такая ситуация, что ядро будет блокировать прерывания в течение значительной части времени, т. е. не будет иметь возможности эффективно реагировать на прерывания. Поэтому ядро обычно разрабатывается таким образом, чтобы оно осуществляло лишь минимально возможную предварительную обработку каждого прерывания, а затем передавало это прерывание на дальнейшую обработку соответствующему системному процессу, после начала работы которого ядро могло бы разрешить последующие прерывания.
Содержание
Основные функции ядра
Основные функция ядра:Ядро операционной системы, как правило, содержит программы для реализации следующих функций:
Типы архитектур ядер операционных систем
Монолитное ядро
Монолитное ядро предоставляет богатый набор абстракций оборудования. Все части монолитного ядра работают в одном адресном пространстве. Это такая схема операционной системы, при которой все компоненты её ядра являются составными частями одной программы, используют общие структуры данных и взаимодействуют друг с другом путём непосредственного вызова процедур. Монолитное ядро — старейший способ организации операционных систем. Примером систем с монолитным ядром является большинство UNIX-систем.
Достоинства: Скорость работы, упрощённая разработка модулей. Недостатки: Поскольку всё ядро работает в одном адресном пространстве, сбой в одном из компонентов может нарушить работоспособность всей системы. Примеры: Традиционные ядра UNIX (такие как BSD), Linux; ядро MS-DOS, ядро KolibriOS.
Монолитные ядра имеют долгую историю развития и усовершенствования и, на данный момент, являются наиболее архитектурно зрелыми и пригодными к эксплуатации. Вместе с тем, монолитность ядер усложняет их отладку, понимание кода ядра, добавление новых функций и возможностей, удаление «мёртвого», ненужного, унаследованного от предыдущих версий кода. «Разбухание» кода монолитных ядер также повышает требования к объёму оперативной памяти, требуемому для функционирования ядра ОС. Это делает монолитные ядерные архитектуры малопригодными к эксплуатации в системах, сильно ограниченных по объёму ОЗУ, например, встраиваемых системах, производственных микроконтроллерах и т. д.
Модульное ядро
Модульное ядро — современная, усовершенствованная модификация архитектуры монолитных ядер операционных систем. В отличие от «классических» монолитных ядер, модульные ядра, как правило, не требуют полной перекомпиляции ядра при изменении состава аппаратного обеспечения компьютера. Вместо этого модульные ядра предоставляют тот или иной механизм подгрузки модулей ядра, поддерживающих то или иное аппаратное обеспечение (например, драйверов). При этом подгрузка модулей может быть как динамической (выполняемой «на лету», без перезагрузки ОС, в работающей системе), так и статической (выполняемой при перезагрузке ОС после переконфигурирования системы на загрузку тех или иных модулей).
Все модули ядра работают в адресном пространстве ядра и могут пользоваться всеми функциями, предоставляемыми ядром. Поэтому модульные ядра продолжают оставаться монолитными. Модульность ядра осуществляется на уровне бинарного образа, а не на архитектурном уровне ядра, так как динамически подгружаемые модули загружаются в адресное пространство ядра и в дальнейшем работают как интегральная часть ядра. Модульные монолитные ядра не следует путать с архитектурным уровнем модульности, присущий микроядрам и гибридным ядрам. Практически, динамичная загрузка модулей, это просто более гибкий способ изменения образа ядра во время выполнения — в отличие от перезагрузки с другим ядром. Модули позволяют легко расширить возможности ядра по мере необходимости.
Модульные ядра удобнее для разработки, чем традиционные монолитные ядра, не поддерживающие динамическую загрузку модулей, так как от разработчика не требуется многократная полная перекомпиляция ядра при работе над какой-либо его подсистемой или драйвером. Выявление, локализация, отладка и устранение ошибок при тестировании также облегчаются. Примером может служить VFS — «виртуальная файловая система», совместно используемая многими модулями файловых систем в ядре Linux.
Микроядро
Микроядро – предоставляет только элементарные функции управления процессами и минимальный набор абстракций для работы с оборудованием. Бо́льшая часть работы осуществляется с помощью специальных пользовательских процессов, называемых сервисами. Решающим критерием «микроядерности» является размещение всех или почти всех драйверов и модулей в сервисных процессах, иногда с явной невозможностью загрузки любых модулей расширения в собственно микроядро, а также разработки таких расширений.
Достоинства: Устойчивость к сбоям оборудования, ошибкам в компонентах системы. Основное достоинство микроядерной архитектуры — высокая степень модульности ядра операционной системы. Это существенно упрощает добавление в него новых компонентов. В микроядерной операционной системе можно, не прерывая её работы, загружать и выгружать новые драйверы, файловые системы и т. д. Существенно упрощается процесс отладки компонентов ядра, так как новая версия драйвера может загружаться без перезапуска всей операционной системы. Компоненты ядра операционной системы ничем принципиально не отличаются от пользовательских программ, поэтому для их отладки можно применять обычные средства. Микроядерная архитектура повышает надежность системы, поскольку ошибка на уровне непривилегированной программы менее опасна, чем отказ на уровне режима ядра.
Недостатки: Передача данных между процессами требует накладных расходов. Классические микроядра предоставляют лишь очень небольшой набор низкоуровневых примитивов, или системных вызовов, реализующих базовые сервисы операционной системы.
Сервисные процессы (в принятой в семействе UNIX терминологии — «демоны») активно используются в самых различных ОС для задач типа запуска программ по расписанию (UNIX и Windows NT), ведения журналов событий (UNIX и Windows NT), централизованной проверки паролей и хранения пароля текущего интерактивного пользователя в специально ограниченной области памяти (Windows NT). Тем не менее, не следует считать ОС микроядерными только из-за использований такой архитектуры. Примеры: Symbian OS; Windows CE; OpenVMS; Mach, используемый в GNU/Hurd и Mac OS X; QNX; AIX; Minix; ChorusOS; AmigaOS; MorphOS.
Экзоядро
Экзоядро — ядро операционной системы, предоставляющее лишь функции для взаимодействия между процессами и безопасного выделения и освобождения ресурсов. Предполагается, что API для прикладных программ будут предоставляться внешними по отношению к ядру библиотеками (откуда и название архитектуры). Возможность доступа к устройствам на уровне контроллеров позволит эффективней решать некоторые задачи, которые плохо вписываются в рамки универсальной ОС, например, реализация СУБД будет иметь доступ к диску на уровне секторов диска, а не файлов и кластеров, что положительно скажется на быстродействии.
Наноядро
Наноядро — архитектура ядра операционной системы, в рамках которой крайне упрощённое и минималистичное ядро выполняет лишь одну задачу — обработку аппаратных прерываний, генерируемых устройствами компьютера. После обработки прерываний от аппаратуры наноядро, в свою очередь, посылает информацию о результатах обработки (например, полученные с клавиатуры символы) вышележащему программному обеспечению при помощи того же механизма прерываний. Примером является KeyKOS — самая первая ОС на наноядре. Первая версия вышла ещё в 1983-м году.
Гибридное ядро
Гибридные ядра — это модифицированные микроядра, позволяющие для ускорения работы запускать «несущественные» части в пространстве ядра. Имеют «гибридные» достоинства и недостатки.
Комбинация разных подходов
Все подходы к построению операционных систем имеют свои достоинства и недостатки. В большинстве случаев современные операционные системы используют различные комбинации этих подходов. Так, например, сейчас ядро «Linux» представляет собой монолитную систему с отдельными элементами модульного ядра. При компиляции ядра можно разрешить динамическую загрузку и выгрузку очень многих компонентов ядра — так называемых модулей. В момент загрузки модуля его код загружается на уровне системы и связывается с остальной частью ядра. Внутри модуля могут использоваться любые экспортируемые ядром функции.
Существуют варианты ОС GNU, в которых вместо монолитного ядра применяется ядро Mach (такое же, как в Hurd), а поверх него крутятся в пользовательском пространстве те же самые процессы, которые при использовании Linux были бы частью ядра. Другим примером смешанного подхода может служить возможность запуска операционной системы с монолитным ядром под управлением микроядра. Микроядро обеспечивает управление виртуальной памятью и работу низкоуровневых драйверов. Все остальные функции, в том числе взаимодействие с прикладными программами, осуществляются монолитным ядром. Данный подход сформировался в результате попыток использовать преимущества микроядерной архитектуры, сохраняя по возможности хорошо отлаженный код монолитного ядра.
Смешанное ядро, в принципе, должно объединять преимущества монолитного ядра и микроядра: казалось бы, микроядро и монолитное ядро — крайности, а смешанное — золотая середина. В них возможно добавлять драйверы устройств двумя способами: и внутрь ядра, и в пользовательское пространство. Но на практике концепция смешанного ядра часто подчёркивает не только достоинства, но и недостатки обоих типов ядер. Примеры: Windows NT, DragonFlyBSD.
Ядро операционной системы, его виды и его архитектура
Ядро́ (kernel) — центральная часть ОС, обеспечивающая приложениям координированный доступ к ресурсам компьютера, таким как процессорное время, память, внешнее аппаратное обеспечение, внешнее устройство ввода и вывода информации. Также обычно ядро предоставляет сервисы файловой системы и сетевых протоколов.
Как основополагающий элемент ОС, ядро представляет собой наиболее низкий уровень абстракции для доступа приложений к ресурсам системы, необходимым для их работы. Как правило, ядро предоставляет такой доступ исполняемым процессам соответствующих приложений за счёт использования механизмов межпроцессного взаимодействия и обращения приложений к системным вызовам ОС.
Виды архитектур ядер операционных систем:
Монолитное ядро ОС
Представляет богатый набор оборудования. Все компоненты монолитного ядра находятся в одном адресном пространстве. Эта схема ОС, когда все части ее ядра — это составные части одной программы. Монолитное ядро — самый старый способ организации ОС.
Достоинства: высокая скорость работы, простая разработка модулей.
Недостатки: Ошибка работы одного из компонентов ядра нарушает работу всей системы.
Модульное ядро ОС
Это современная модификация монолитных ядер ОС, но в отличие от них модульное ядро не требует полной перекомпиляции ядра при изменения аппаратного обеспечения компьютера. Более того модульные ядра имеют механизм погрузки модулей ядра. Погрузка бывает статической- с перезагрузкой ОС, и динамической — без перезагрузки ОС.
Микроядро ОС
Представляет только основные функции управления процессами и минимальный набор для работы с оборудованием.
Достоинства: устойчивость к сбоям и ошибкам оборудования и компонентов системы, высокая степень ядерной модульности, что упрощает добавление в ядро новых компонентов и процесс отладки ядра.
Недостатки: Передача информации требует больших расходов и большого количества времени.
Экзоядро ОС
Такое ядро ОС, которое предоставляет лишь функции взаимодействия процессов, безопасное выделение и распределение ресурсов. Доступ к устройствам на уровне контроллеров позволяет решать задачи, которые нехарактерны для универсальной ОС.
Наноядро ОС
Такое ядро выполняет только единственную задачу- обработку аппаратных прерываний, образуемых устройствами ПК. После обработки наноядро посылает данные о результатах обработки далее идущему в цепи программному обеспечения при помощи той же системы прерываний.
Гибридное ядро ОС
Модификация микроядер, позволяющая для ускорения работы впускать несущественные части в пространство ядра. На архитектуре гибкого ядра построены последние операционные системы от Windows, в том числе и Windows 7-10.
В чем разница между пространством ядра и пользовательским пространством?
В чем разница между пространством ядра и пользовательским пространством? Имеют ли место ядра, потоки ядра, процессы ядра и стек ядра то же самое? Кроме того, зачем нам эта дифференциация?
Действительно упрощенный ответ заключается в том, что ядро работает в пространстве ядра, а обычные программы запускаются в пространстве пользователя. Пользовательское пространство в основном представляет собой форму песочного бокса – оно ограничивает пользовательские программы, поэтому они не могут взаимодействовать с памятью (и другими ресурсами), принадлежащими другим программам или ядром ОС. Это ограничивает (но обычно не полностью устраняет) их способность делать плохие вещи, такие как сбой машины.
Ядро является ядром операционной системы. Он обычно имеет полный доступ ко всему аппарату памяти и оборудования (и все остальное на машине). Чтобы машина была как можно более стабильной, вы обычно хотите, чтобы в режиме ядра/ядра находился только самый надежный, хорошо протестированный код.
Стек – это еще одна часть памяти, поэтому, естественно, она разделяется прямо вместе с остальной памятью.
Оперативное запоминающее устройство (ОЗУ) может быть логически разделено на две отдельные области, а именно – пространство ядра и пространство пользователя (физические адреса ОЗУ фактически не делятся только на виртуальные адреса, все это реализуется MMU)
Системные вызовы действуют как интерфейс между пользовательскими процессами и процессами ядра. Права доступа размещены в пространстве ядра, чтобы пользователи не могли не связываться с ядром по незнанию.
Таким образом, когда происходит системный вызов, программному прерыванию отправляется ядро. Процессор может временно передать управление соответствующей подпрограмме обработки прерывания. Процесс ядра, который был остановлен прерываниями, возобновляется после того, как процедура обработчика прерываний завершает свою работу.
Пространство ядра и виртуальное пространство – это понятия виртуальной памяти… это не означает, что Ram (ваша фактическая память) разделен на ядро и пространство пользователя. Каждому процессу предоставляется виртуальная память, которая делится на ядро и пространство пользователя.
Таким образом, говоря: “Оперативная память (RAM) может быть разделена на две отдельные области, а именно – пространство ядра и пространство пользователя”. неправильно.
& относительно вещи “пространство ядра против пространства пользователя”
Когда процесс создан и его виртуальная память разделена на пользовательское пространство и пространство ядра, где область пользовательского пространства содержит данные, код, стек, кучу процесса и пространство ядра содержит такие вещи, как таблица страниц для процесса., структуры данных ядра, код ядра и т.д. Для запуска кода пространства ядра управление должно перейти в режим ядра (с использованием программного прерывания 0x80 для системных вызовов), а стек ядра в основном распределяется между всеми процессами, выполняющимися в настоящее время в пространстве ядра.
Кольца процессора – самое четкое различие
В защищенном режиме x86 процессор всегда находится в одном из 4 звонков. Ядро Linux использует только 0 и 3:
Это наиболее сложное и быстрое определение ядра и пользовательского пространства.
Как определяется текущее кольцо?
Текущее кольцо выбирается комбинацией:
таблица глобальных дескрипторов: таблица в памяти записей GDT, и каждая запись имеет поле Privl которое кодирует кольцо.
Инструкция LGDT устанавливает адрес для текущей таблицы дескрипторов.
Сегмент регистрирует CS, DS и т.д., которые указывают на индекс записи в GDT.
Например, CS = 0 означает, что первая запись GDT в данный момент активна для исполняемого кода.
Что может сделать каждое кольцо?
Чип процессора физически построен так, что:
кольцо 0 может сделать что угодно
кольцо 3 не может выполнить несколько инструкций и записать в несколько регистров, в частности:
не может изменить свое собственное кольцо! В противном случае он мог бы установить себе кольцо 0, и кольца были бы бесполезны.
Другими словами, нельзя изменить текущий дескриптор сегмента, который определяет текущее кольцо.
не может изменить таблицы страниц: как работает подкачка x86?
Другими словами, нельзя изменить регистр CR3, а само разбиение на страницы предотвращает изменение таблиц страниц.
Это препятствует тому, чтобы один процесс видел память других процессов из соображений безопасности/простоты программирования.
не может зарегистрировать обработчики прерываний. Они настраиваются путем записи в ячейки памяти, что также предотвращается подкачкой.
Обработчики работают в кольце 0 и нарушают модель безопасности.
Другими словами, нельзя использовать инструкции LGDT и LIDT.
В противном случае, например, права доступа к файлам будут бесполезны, если какая-либо программа сможет напрямую читать с диска.
Точнее, благодаря Майклу Петчу: операционная система может разрешить инструкции ввода-вывода на 3-м кольце, это фактически контролируется сегментом состояния задачи.
То, что невозможно, это для кольца 3, чтобы дать себе разрешение сделать это, если у него не было его в первую очередь.
Как программы и операционные системы переходят между кольцами?
когда процессор включен, он запускает исходную программу в кольце 0 (что-то вроде, но это хорошее приближение). Вы можете считать эту исходную программу ядром (но обычно это загрузчик, который затем вызывает ядро все еще в кольце 0).
когда пользовательский процесс хочет, чтобы ядро сделало что-то для него, например, запись в файл, он использует инструкцию, которая генерирует прерывание, такое как int 0x80 или syscall для сигнализации ядра. x86-64 Linux syscall hello world пример:
скомпилируйте и запустите:
Когда это происходит, ЦП вызывает обработчик обратного вызова прерывания, который ядро зарегистрировало во время загрузки. Вот конкретный пример с использованием неизолированного металла, который регистрирует обработчик и использует его.
Этот обработчик работает в кольце 0, который решает, разрешит ли ядро это действие, выполняет действие и перезапускает программу userland в кольце 3. x86_64
когда используется системный вызов exec (или когда ядро запустится /init ), ядро подготавливает регистры и память нового пользовательского процесса, затем переходит к точке входа и переключает ЦП на вызов 3
Если программа пытается сделать что-то непослушное, например запись в запрещенный регистр или адрес памяти (из-за подкачки), ЦП также вызывает некоторый обработчик обратного вызова ядра в кольце 0.
Когда ядро загружается, оно устанавливает аппаратные часы с некоторой фиксированной частотой, которая периодически генерирует прерывания.
Эти аппаратные часы генерируют прерывания, которые запускают кольцо 0, и позволяют ему планировать, какие процессы пользователя активизируются.
Таким образом, планирование может происходить, даже если процессы не выполняют никаких системных вызовов.
Какой смысл иметь несколько колец?
Существует два основных преимущества разделения ядра и пользовательского пространства:
Как поиграться с этим?
Я создал “голую железную” установку, которая должна быть хорошим способом для непосредственного управления кольцами: https://github.com/cirosantilli/x86-bare-metal-examples
К сожалению, у меня не хватило терпения сделать пример пользовательского пространства, но я дошел до настройки пейджинга, поэтому пользовательское пространство должно быть выполнимым. Я хотел бы увидеть запрос на получение.
В качестве альтернативы модули ядра Linux работают в кольце 0, поэтому вы можете использовать их для проверки привилегированных операций, например, для чтения управляющих регистров: как получить доступ к управляющим регистрам cr0, cr2, cr3 из программы? Получение ошибки сегментации
Вот удобная настройка QEMU + Buildroot, чтобы попробовать ее, не убивая своего хоста.
Недостатком модулей ядра является то, что другие kthreads работают и могут мешать вашим экспериментам. Но в теории вы можете взять на себя все обработчики прерываний с вашим модулем ядра и владеть системой, это был бы действительно интересный проект.
Отрицательные кольца
Хотя отрицательные кольца фактически не упоминаются в руководстве Intel, на самом деле существуют режимы ЦП, которые имеют более широкие возможности, чем само кольцо 0, и поэтому хорошо подходят для имени “отрицательного кольца”.
Одним из примеров является режим гипервизора, используемый в виртуализации.
РУКА
В ARM кольца называются уровнями исключения, но основные идеи остаются прежними.
В ARMv8 существует 4 уровня исключений, которые обычно используются как:
EL0: пользовательская область
EL1: ядро (“супервизор” в терминологии ARM).
Введено с помощью инструкции svc (SuperVisor Call), ранее известной как swi до унифицированной сборки, которая используется для выполнения системных вызовов Linux. Привет мир ARMv8 пример:
Проверьте это с QEMU на Ubuntu 16.04:
Ниже приведен конкретный пример с использованием неизолированного металла, который регистрирует обработчик SVC и выполняет вызов SVC.
hvc с hvc инструкции hvc (HyperVisor Call).
Гипервизор для ОС, то же самое, что ОС для пользователя.
Например, Xen позволяет одновременно запускать несколько ОС, таких как Linux или Windows, в одной и той же системе и изолирует ОС друг от друга для обеспечения безопасности и простоты отладки, как это делает Linux для пользовательских программ.
Гипервизоры являются ключевой частью современной облачной инфраструктуры: они позволяют нескольким серверам работать на одном оборудовании, поддерживая использование оборудования всегда близким к 100% и экономя много денег.
Например, AWS использовала Xen до 2017 года, когда новость о его переходе на KVM.
EL3: еще один уровень. Пример TODO.
Введено с инструкцией smc (вызов в безопасном режиме)
Эталонная модель архитектуры ARMv8 DDI 0487C.a – Глава D1 – Модель программиста на уровне системы AArch64 – Рисунок D1-1 прекрасно иллюстрирует это:
Обратите внимание, что ARM, возможно, благодаря ретроспективе, имеет лучшее соглашение об именах для уровней привилегий, чем x86, без необходимости использования отрицательных уровней: 0 – нижний, а 3 – самый высокий. Более высокие уровни, как правило, создаются чаще, чем более низкие.
Текущий EL может быть запрошен с помощью инструкции MRS : каков текущий режим выполнения/уровень исключения и т.д.?
ARM не требует наличия всех уровней исключений, чтобы обеспечить реализации, которым не требуется эта функция для сохранения площади микросхемы. ARMv8 “Уровни исключений” говорит:
Реализация может не включать все уровни исключений. Все реализации должны включать EL0 и EL1. EL2 и EL3 являются необязательными.
Например, QEMU по умолчанию имеет значение EL1, но EL2 и EL3 можно включить с помощью параметров командной строки: qemu-system-aarch64 вводит el1 при эмуляции включения питания a53
Фрагменты кода, протестированные на Ubuntu 18.10.
Ядро и пространство пользователя – это разделение привилегированных функций операционной системы и ограниченных пользовательских приложений. Разделение необходимо, чтобы пользовательские приложения не могли обыгрывать ваш компьютер. Было бы плохо, если бы какая-либо старая пользовательская программа могла начать записывать случайные данные на ваш жесткий диск или читать память из другого пространства памяти пользовательской программы.
Пользовательские космические программы не могут напрямую обращаться к системным ресурсам, так что доступ к файлу зависит от имени программы от ядра операционной системы. Программы пользовательского пространства обычно делают такие запросы операционной системы через системные вызовы.
Нити, процессы, стеки ядра не означают одно и то же. Они представляют собой аналогичные конструкции для пространства ядра как их аналоги в пользовательском пространстве.
Каждый процесс имеет свою собственную 4 ГБ виртуальной памяти, которая сопоставляется с физической памятью через таблицы страниц. Виртуальная память в основном разделена на две части: 3 ГБ для использования процесса и 1 ГБ для использования ядра. Большинство создаваемых вами переменных лежат в первой части адресного пространства. Эта часть называется пользовательским пространством. Последняя часть – это то, где ядро проживает и является общим для всех процессов. Это называется пространством ядра, и большая часть этого пространства отображается в начальные местоположения физической памяти, где изображение ядра загружается во время загрузки.
Максимальный размер адресного пространства зависит от длины регистра адреса в CPU.
Такое адресное пространство называется виртуальной памятью или виртуальным адресным пространством. Фактически это не связано с размером физической оперативной памяти.
На платформах Linux виртуальное адресное пространство делится на пространство ядра и пространство пользователя.
В конкретной 32-битной системе, например, 3 GiB может быть занята для пользовательского пространства и 1 GiB для пространства ядра.
Ядро-поток – это легкий процесс, а также исполняемая программа.
Один процесс может состоять из нескольких потоков, разделяющих одни и те же данные и ресурсы, но с помощью программного кода с различными путями. Linux предоставляет системный вызов clone() для генерации потоков.
Примеры использования потоков ядра: синхронизация данных ОЗУ, помогающая планировщику распределять процессы между ЦП и т.д.
Вкратце: ядро работает в пространстве ядра, пространство ядра имеет полный доступ ко всей памяти и ресурсам, вы можете сказать, что разделение памяти на две части, часть для ядра и часть для собственного процесса пользователя (пространство пользователя) работает нормально программы, пространство пользователя не может напрямую обращаться к ядру, поэтому он запрашивает у ядра использовать ресурсы. syscall (предопределенный системный вызов в glibc)
существует инструкция, которая упрощает различные “ Пользовательское пространство – это просто тестовая нагрузка для ядра“…
Чтобы быть предельно ясным: архитектура процессора позволяет процессору работать в двух режимах: Режим ядра и пользовательский режим, инструкция Hardware позволяет переключиться с одного режима на другой.
память может быть помечена как часть пространства пользователя или пространства ядра.
Когда процессор работает в пользовательском режиме, CPU может получить доступ только к памяти, находящейся в пространстве пользователя, а процессор пытается получить доступ к памяти в ядре. Результат – это “аппаратное исключение”, когда процессор работает в режиме ядра, процессор может получить доступ непосредственно к пространству ядра и пользовательскому пространству…
Ядро Linux относится ко всему, что работает в режиме ядра, и состоящий из нескольких отдельных слоев. В самом нижнем слое ядро взаимодействует с оборудованием через HAL. На среднем уровне Ядро UNIX разделено на 4 отдельные области. Первый из четырех области обрабатывают символьные устройства, сырые и приготовленные TTY и терминалы обработки. Вторая область обрабатывает драйверы сетевых устройств, маршрутизацию протоколов и сокетов. Третья область обрабатывает драйверы дисковых устройств, кэша страниц и буфера, файловой системы, виртуальной памяти, именования файлов и отображение. Четвертая и последняя область обрабатывает диспетчеризацию процесса, планирование, создание и завершение, а также обработку сигналов. Прежде всего, у нас есть верхний слой ядра, который включает системные вызовы, прерывания и ловушки. Этот уровень служит интерфейс к каждой из функций нижнего уровня. Программист использует различные системные вызовы и прерывания для взаимодействия с функциями операционной системы.
В коротком пространстве ядра – это часть памяти, в которой работает linux kernel (верхнее 1 ГБ виртуального пространства в случае Linux), а пространство пользователя – это часть памяти, в которой выполняется пользовательское приложение (нижняя 3 ГБ виртуальной памяти в случае Linux Если вы хотите узнать больше, см. Ссылку ниже:)
Ядро означает, что пространство памяти может быть затронуто только ядром. В 32-битном Linux это 1G (от 0xC0000000 до 0xffffffff как адрес виртуальной памяти). Каждый процесс, созданный ядром, также является потоком ядра. Итак, для одного процесса есть два стека: один стек в пользовательском пространстве для этого процесса, а другой в ядре пространство для потока ядра.
стек ядра занял 2 страницы (8k в 32-битном Linux), включил task_struct (около 1k) и реальный стек (около 7k). Последний используется для хранения некоторых автоматических переменных или параметров вызова функции или адреса функции в функциях ядра. Вот код (Processor.h(linux\include\asm-i386)):
__ get_free_pages (GFP_KERNEL, 1)) означает выделение памяти как 2 ^ 1 = 2 страницы.
Но стек процесса – это еще одна вещь, его адрес просто ниже 0xC0000000 (32-битный linux), размер которого может быть довольно большим, используется для вызовов функции пространства пользователя.
Итак, вот вопрос для системного вызова, он работает в пространстве ядра, но вызван процессом в пользовательском пространстве, как он работает? Будет ли linux помещать свои параметры и адрес функции в стек ядра или стек процесса? Решение Linux: все системные вызовы инициируются прерыванием программного обеспечения INT 0x80.
Определено в entry.S(linux\arch\i386\kernel), вот несколько строк, например:
Попытка дать очень упрощенное объяснение
Виртуальная память делится на пространство ядра и пространство пользователя.
Ядро – это область виртуальной памяти, в которой будут выполняться процессы ядра, а пространство пользователя – это область виртуальной памяти, в которой будут выполняться процессы пользователя.
Это разделение требуется для защиты доступа к памяти.
Всякий раз, когда загрузчик запускает ядро после загрузки его в место в ОЗУ (обычно на контроллере на основе ARM), он должен убедиться, что контроллер находится в режиме супервизора с отключенным FIQ и IRQ.
Правильный ответ: нет такой вещи, как пространство ядра и пространство пользователя. Набор инструкций процессора имеет специальные разрешения для установки деструктивных вещей, таких как корень таблицы таблиц страниц, или доступ к памяти устройства устройства и т.д.
Код ядра имеет привилегии наивысшего уровня, а код пользователя – самый низкий. Это предотвращает сбой кода пользователя, изменение других программ и т.д.
В общем случае код ядра хранится под другой картой памяти, чем код пользователя (так же, как пространство пользователя хранится в разных картах памяти, чем между собой). Здесь происходят термины “пространство ядра” и “пользовательское пространство”. Но это не сложное и быстрое правило. Например, поскольку x86 косвенно требует, чтобы обработчики прерываний/ловушек отображались в любое время, часть (или некоторые ОС всех) ядра должны отображаться в пространстве пользователя. Опять же, это не означает, что такой код имеет пользовательские привилегии.
Почему требуется разделение ядра/пользователя? Некоторые дизайнеры не согласны с тем, что это действительно необходимо. Архитектура Microkernel основана на идее, что наивысшие привилегированные разделы кода должны быть как можно меньше, при этом все важные операции выполняются в привилегированном коде пользователя. Вам нужно будет изучить, почему это может быть хорошей идеей, это не простая концепция (и славится тем, что у нее есть преимущества и недостатки).
Пространство ядра и пространство пользователя являются логическими пространствами.
Большинство современных процессоров предназначены для работы в разных привилегированных режимах. Машины x86 могут работать в 4 различных привилегированных режимах.
И конкретная машинная инструкция может быть выполнена, когда в/выше конкретного привилегированного режима.
Из-за этого дизайна вы предоставляете защиту системы или песочницу среды выполнения.
Ядро – это кусок кода, который управляет вашим оборудованием и обеспечивает системную абстракцию. Таким образом, он должен иметь доступ ко всем инструкциям машины. И это самая надежная часть программного обеспечения. Так что я должен быть казнен с высшей привилегией. И уровень Кольца 0 – самый привилегированный режим. Поэтому Ring Level 0 также называется Kernel Mode.
Пользовательское приложение – это часть программного обеспечения от сторонних поставщиков, и вы не можете им полностью доверять. Кто-то со злым умыслом может написать код для сбоя вашей системы, если у него был полный доступ ко всем инструкциям машины. Поэтому приложение должно иметь доступ к ограниченному набору инструкций. А Ring Level 3 – наименее привилегированный режим. Таким образом, все ваше приложение работает в этом режиме. Следовательно, уровень 3 звонка также называется режимом пользователя.
Примечание: я не получаю Уровни Кольца 1 и 2. В основном это режимы с промежуточными привилегиями. Так может быть код драйвера устройства выполняется с этой привилегией. AFAIK, linux использует только Ring Level 0 и 3 для выполнения кода ядра и пользовательского приложения соответственно.
Таким образом, любая операция, происходящая в режиме ядра, может рассматриваться как пространство ядра. И любая операция, происходящая в пользовательском режиме, может рассматриваться как пространство пользователя.
Память делится на две отдельные области:
Процессы, выполняющиеся в пространстве пользователя, имеют доступ только к ограниченной части памяти, тогда как ядро имеет доступ ко всей памяти. Процессы, выполняющиеся в пространстве пользователя, также не имеют доступа к пространству ядра. Процессы пользовательского пространства могут получить доступ только к небольшой части ядра через интерфейс, предоставляемый ядром – системные вызовы. Если процесс выполняет системный вызов, в ядро отправляется программное прерывание, которое затем отправляет соответствующий обработчик прерываний и продолжает его работа после того, как обработчик закончил.