Расположение ОС данных ядра - PullRequest
0 голосов
/ 08 января 2019

Я новичок в операционных системах, и у меня возник вопрос по поводу ядра ОС.

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

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

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

Наконец, я видел несколько диаграмм, на которых код ОС расположен в верхней части адресного пространства пользовательской программы. Здесь находится все ядро ​​ОС? Если нет, где еще находится код ядра ОС?

Спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 08 января 2019

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

В каждой современной операционной системе, которую я знаю, НИКОГДА не происходит переключение контекста на ядро. Ядро выполняется в контексте процесса (в некоторых системах пользователь выдает сокращенный контекст процесса.

«Ядро» выполняется, когда процесс входит в режим ядра через исключение или прерывание.

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

https://books.google.com/books?id=FSX5qUthRL8C&pg=PA322&lpg=PA322&dq=vax+%22interrupt+stack%22&source=bl&ots=CIaxuaGXWY&sig=S-YsXBR5_kY7hYb6F2pLGjn5pn4&hl=en&sa=X&ved=2ahUKEwjrgvyX997fAhXhdd8KHdT7B8sQ6AEwCHoECAEQAQ#v=onepage&q=vax%20%22interrupt%20stack%22&f=false

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

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

Где расположены эти структуры данных? Находятся ли они в адресных пространствах пользовательских программ?

Они обычно находятся в системном пространстве. Однако некоторые системы помещают некоторые структуры в пространство пользователя в защищенную память.

Они находятся в каком-то выделенном сегменте памяти для структур данных ядра?

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

Они разбросаны по всей физической памяти, где есть место?

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

0 голосов
/ 08 января 2019

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

Код, работающий в ядре, сам по себе не рассматривается как «процесс». Код является привилегированным , что означает, что он может изменять любые данные в ядре, устанавливать привилегированные биты в регистрах процессора, отправлять прерывания, взаимодействовать с устройствами, выполнять привилегированные инструкции и т. Д. Он не ограничен, как код пользователя процесс.

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

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

Каждый процесс имеет свое собственное виртуальное адресное пространство. Это означает, что некоторый виртуальный адрес a в одном процессе может отображаться на физический адрес, отличный от того же виртуального адреса a в другом процессе. Виртуальная память имеет много важных применений, но я не буду вдаваться в них здесь. Важным моментом является то, что виртуальная память обеспечивает изоляцию памяти . Это означает, что процесс A не может получить доступ к памяти процесса B. Все виртуальные адреса процесса A отображаются на некоторый набор физических адресов, а все виртуальные адреса процесса B отображаются на другой набор физических адресов. Пока два набора физических адресов не перекрываются, процессы не могут видеть или изменять память друг друга. Пользовательские процессы не могут обращаться к физическим адресам памяти напрямую - они могут осуществлять доступ к памяти только с виртуальными адресами.

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

Теперь ответим на ваш вопрос об адресных пространствах ядра и адресных пространствах пользователей.

Ядро может иметь отдельное виртуальное адресное пространство от каждого пользовательского процесса. Это так же просто, как изменение указателя каталога страниц в регистре cr3 (в процессоре x86) при каждом переключении контекста. Поскольку ядро ​​имеет другое виртуальное адресное пространство, ни один пользовательский процесс не может получить доступ к памяти ядра, если ни один из адресов виртуальной памяти ядра не сопоставляется с теми же физическими адресами, что и любой из виртуальных адресов в любом адресном пространстве для пользовательского процесса.

Это может привести к незначительной проблеме. Если пользовательский процесс выполняет системный вызов и передает указатель в качестве параметра (например, указатель на буфер в системном вызове read), как ядро ​​узнает, какой физический адрес соответствует этому буферу? Виртуальный адрес в указателе отображается на другой физический адрес в пространстве ядра, поэтому ядро ​​не может просто разыменовать указатель. Есть два варианта:

  1. Ядро может просматривать каталог / таблицы страниц пользовательского процесса, чтобы найти физический адрес, который соответствует буферу. Затем ядро ​​может выполнять чтение / запись с / на этот физический адрес.

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

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

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

Посмотрите эти слайды для получения дополнительной информации.

...