Как процессор обрабатывает случай деления на ноль

Любопытно, что делает процессор / ЦП в целом или, скажем, на процессоре Intel и Linux, когда он выполняет команду деления на ноль. Также как ошибка передается в приложение, чтобы оно могло зарегистрировать ошибку или уведомить разработчика?

Спасибо!


person Alfred    schedule 26.05.2014    source источник
comment
Какой процессор? Какая ОС?   -  person Oliver Charlesworth    schedule 27.05.2014
comment
@OliCharlesworth Ах, только что отредактировал вопрос. По сути, я просто хочу получить общее представление о том, как работает весь процесс. Можно предположить, что это Linux на процессоре Intel.   -  person Alfred    schedule 27.05.2014


Ответы (3)


Чтобы ответить в общих чертах, а не вдаваться в кровавые подробности для Linux на x86_64, которые, вероятно, затемняют концепции.

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

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

На некоторых процессорах RISC программные ловушки в ОС будут запускаться для исправления несогласованных обращений к данным, поэтому чтение памяти будет работать, но со снижением производительности. Раньше ловушки иногда использовались для эмуляции определенных инструкций, но которые не были реализованы аппаратно с помощью конкретной модели ЦП. Я также видел, как регистрируются ошибки аппаратной памяти, поскольку ОС инициирует операцию восстановления памяти ECC, хотя на x86 это обрабатывается по-другому.

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

person Rob11311    schedule 26.05.2014
comment
Правильно, пытался отличить их от прерываний, генерируемых периферийными устройствами, быстрые объяснения могут быть такими сложными - person Rob11311; 27.05.2014
comment
@ Rob11311 Эти прерывания улавливаются, например, когда аппаратные прерывания останавливают выполнение текущей программы и возвращают управление ОС, поэтому все это обрабатывается процессором, т.е. реализуется аппаратно или прошивкой (поскольку на этом этапе ОС не имеет контроля) , правильно? - person Alfred; 02.06.2014
comment
Да, это железо. Планировщик ОС может восстановить управление, запланировав прерывание по таймеру, даже если не происходит никаких других прерываний (периферийные устройства или системные вызовы), поэтому на самом деле он просто передает ЦП пользовательской программе. - person Rob11311; 02.06.2014

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

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

person user3344003    schedule 27.05.2014

Когда ошибка DIV0 происходит «в процессоре», приложение не сможет ничего регистрировать (если не управляют некоторые дочерние процессы).

DIV0 почти никогда не происходит в процессоре, его ловят:

$  echo $(( 1/0 ))
bash: 1/0 : division by 0 (error token is "0 ")

Это не доказательство - может быть, журнал. Но он начинается с bash: и учитывает пробел в ошибочном токене "0 ".

На Pentium это самая первая запись в таблице.

На этом User33 завершает свое подробное описание. Я попал сюда из-за вопросов к планировщику, где я использовал пример DIV0 в ЦП, чтобы проиллюстрировать (внезапное) «блокирование» (лучше: остановку) этого процесса. Моя точка зрения такова: процессоры следуют традициям и логике, отказываясь делить на ноль, включая любые дешевые хаки. Это по определению точка. Не должно происходить, но если, то дальнейшая инструкция не обрабатывается. Вместо этого используется эта особенная первая запись. Особый, потому что это самый простой случай, когда ЦП выдает исключение «невозможно продолжить».

Без защищенного режима div0 в процессоре вызывает сбой системы. Но благодаря этим специальным скрытым таблицам и функциям в защищенном режиме ядро ​​/ планировщик может перезапустить ЦП и продолжить работу без остановленного процесса. Этот процесс мертв и будет удален - нужно запустить еще один, как и первый;)

person rastafile    schedule 19.10.2019