Как ОС ограничивает возможности программы, если она работает напрямую с процессором?
Когда программа загружается в память и начинает работать, процессор загружает каждую инструкцию из кода и выполняет инструкцию на основе кода операции и аргументов, поэтому программа взаимодействует, так сказать, напрямую с процессором.
Однако ОС (linux / win) не позволяет вам делать все, поэтому вам придется спрашивать ее разрешение на некоторые вещи - с помощью системных вызовов. Но мне интересно, почему пользовательский код не может делать определенные вещи, которые может делать ОС - какая разница для ЦП, выполняет ли код ядра ОС команду или выполняет пользователь?
Проверяет ли ОС мой код перед его загрузкой и видит, использую ли я там определенные инструкции, которые мне не разрешено использовать, и если да, то просто не выполнит их?
Как это делается?
Кстати, ассемблер - это язык программирования, поэтому программист может выбрать любую инструкцию для использования в коде.
Ответы
Современные процессоры имеют режимы привилегий, которые используются операционной системой для блокировки определенных инструкций. Например, в user
режиме инструкции, которые изменяют (повышают) режим привилегий или получают доступ к системным ресурсам, таким как текущие настроенные таблицы страниц, вызывают исключения. Это позволяет операционной системе решить, прервать ли пользовательский процесс или эмулировать операцию.
Проверяет ли ОС мой код перед его загрузкой и видит, использую ли я там определенные инструкции, которые мне не разрешено использовать, и если да, то просто не выполнит их?
Нет, это не обязательно - операционная система переводит процессор в «пользовательский» режим всякий раз, когда он запускает пользовательский код. Это активирует аппаратный механизм исключений, если встретится привилегированная инструкция - в пользовательском режиме исключение происходит вместо выполнения привилегированной инструкции (запуск исключения - это выполнение этой инструкции, а не какой-либо привилегированной операции).
Кстати, типы инструкций системного вызова, используемые кодом пользовательского режима для запроса услуг из операционной системы, также активируют механизм аппаратных исключений.
Как это делается?
Операционная система всегда запускает пользовательский код в пользовательском режиме, также называемом привилегиями пользовательского уровня, и обычно запускает свой собственный код с более высокими привилегиями. Эти режимы информируют процессор, как обрабатывать привилегированные инструкции. Большая часть кода пользовательского режима даже не потрудится попытаться выполнить привилегированные инструкции, поскольку они бесполезны, но если они это сделают, срабатывает механизм аппаратных исключений и эффективно сообщает операционной системе, что это произошло, и позволяет ей справиться с ситуацией.
Чтобы запустить код пользовательского режима, операционная система может использовать команду «возврата из прерывания», чтобы перезапустить пользовательский код (независимо от того, был ли он ранее запущен технически или нет). Возврат из прерывания - это тип инструкции, который является одним из способов изменить уровень привилегий, а также изменить поток инструкций (также известный как ветвление); такая инструкция является привилегированной, то есть процессор не разрешает ее в пользовательском режиме.
Когда процессор получает прерывание, он отмечает некоторые из критических состояний ЦП - критическое состояние ЦП - это то состояние, которое он обязательно должен изменить для обслуживания прерывания. При обслуживании прерывания управление потоком команд передается в ЦП путем изменения счетчика программ, также известного как указатель команд; при прерывании процессор эффективно выполняет внезапный переход к программе обслуживания прерывания. Он также внезапно меняет режим на более высокие привилегии, что позволяет ISR получить доступ к большему количеству инструкций. Поскольку эти два внезапных изменения необходимы для активации ISR, оборудование запишет предыдущие значения для программного обеспечения, которое будет использоваться позже при возобновлении кода прерванного режима пользователя. Таким образом, аппаратное обеспечение и операционная система работают вместе, чтобы запускать ОС с высокими привилегиями, а пользовательский код - с низкими привилегиями.
Когда программа пользовательского режима использует команду типа системного вызова (запрашивая службы операционной системы, такие как ввод-вывод), тот же механизм аппаратных исключений передает управление ISR. Когда операционная система хочет возобновить процесс пользовательского режима, в зависимости от оборудования, ей, возможно, придется вручную продвинуть программный счетчик процесса пользовательского режима по команде системного вызова перед возобновлением - это как если бы для процесса пользовательского режима операционная система смоделировала / эмулировала системный вызов.
Кроме того, все инструкции ЦП вашей программы выполняются в собственном пространстве виртуальной памяти. Это в основном отключает любые инструкции, которые вы кодируете для доступа или изменения системных данных, данных других процессов или данных ядра.
В принципе, вы можете испортить свой дом, как хотите, но вы не можете заглядывать в чужие дома.
Если вы хотите выполнить что-то за пределами вашего адресного пространства, у вас нет другого выбора, кроме как вызывать системные процедуры / службы, которые делают это за вас - и те проверяют авторизацию / привилегии вашего процесса.
Оставаясь на картинке выше, вам нужно использовать надежный сервис, если вы хотите что-то от чужих домов - процедуры ядра ОС.
В этом ответе предполагается, что вы используете современную многозадачную операционную систему (Windows, MacOS, Linux и т. Д.) На процессоре, который имеет специальную аппаратную поддержку для нее (ARM, x86, PowerPC и т. Д.). Он основан на предыдущих ответах Эрика Эйдта и Аганджу.
Эти системы развивались с годами, чтобы стать все более ограничивающими для обычных пользовательских программ.
На такой машине ваша программа не имеет прямого доступа к физической памяти. Все адреса памяти проходят через диспетчер виртуальной памяти. Если в вашем адресном пространстве был выделен конкретный адрес, то этот адрес отображается на адрес физической памяти. В противном случае доступ не удастся, и возникнет ловушка. Операционная система, вероятно, завершит вашу программу. Диспетчер памяти гарантирует, что ни один процесс не сможет повредить память другого процесса.
Аппаратные устройства обычно отображаются в памяти. Опять же, диспетчер памяти блокирует любой прямой доступ к ним. Вы должны вызвать водителя, который сделает это за вас.
Операционная система использует специальные инструкции машинного кода для настройки всего, а также для реализации драйверов устройств. Эти инструкции имеют разные уровни привилегий, необходимые для их выполнения. Когда ваша программа запускается, она будет отмечена операционной системой как пользовательская программа с самыми низкими привилегиями. Таким образом, любая попытка использовать эти инструкции для изменения или обхода управления памятью будет заблокирована. Опять же, ваша программа, скорее всего, будет завершена.