ПРОЦЕССОР
Главная | Регистрация | Вход
Понедельник, 29.04.2024, 17:35
Меню сайта
Мини-чат
Наш опрос
Оцените мой сайт
Всего ответов: 77
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Что делает процессор в компьютере?
Как известно, процессор является основным вычислительным блоком компьютера, в наибольшей степени определяющим его мощь. Процессор является устройством, исполняющим программу - последовательность команд, задуманную программистом и оформленную в виде модуля программного кода. Чтобы понять, что делает процессор, рассмотрим его в окружении системных компонентов IBM PC-совместимого компьютера. Этой компьютерной архитектурой, естественно, не ограничивается сфера применения процессоров семейства x86, которым посвящена данная книга.
    Всем известный IBM PC-совместимый компьютер представляет собой реализацию так называемой фон-неймановской архитектуры вычислительных машин. Эта архитектура была предложена Джорджем фон Нейманом еще в 1945 году и имеет следующие основные признаки. Машина состоит из блока управления, арифметико-логического устройства (АЛУ), памяти и устройств ввода-вывода. В ней реализуется концепция хранимой программы: программы и данные хранятся в одной и той же памяти. Выполняемые действия определяются блоком управления и АЛУ, которые вместе являются основой центрального процессора. Центральный процессор выбирает и исполняет команды из памяти последовательно, адрес очередной команды задается "счетчиком адреса" в блоке управления. Этот принцип исполнения называется последовательной передачей управления. Данные, с которыми работает программа, могут включать переменные - именованные области памяти, в которых сохраняются значения с целью дальнейшего использования в программе. Фон-неймановская архитектура - не единственный вариант построения ЭВМ, есть и другие, которые не соответствуют указанным принципам (например, потоковые машины). Однако подавляющее большинство современных компьютеров основано именно на этих принципах, включая и сложные многопроцессорные комплексы, которые можно рассматривать как объединение фон-неймановских машин. Конечно же, за более чем полувековую историю ЭВМ классическая архитектура прошла длинный путь развития. Тем не менее ПК можно разложить "по полочкам" следующим образом.
    Центральный процессор
(АЛУ с блоком управления) реализуется микропроцессором семейства x86 - от 8086/88 до Pentium 4 и Athlon (и это не конец истории). При всей своей внутренней суперскалярности, суперконвейеризированности и спекулятивности (см. п. 1.3), внешне процессор соблюдает вышеупомянутый принцип последовательной передачи управления. Набор арифметических, логических и прочих инструкций (см. главу 4) насчитывает несколько сотен, а для потоковой обработки придуман принцип SIMD - множество комплектов данных, обрабатываемых одной инструкцией (расширения MMX, 3DNow!, SSE). Процессор имеет набор регистров (см. п. 2.2), часть которых доступна для хранения операндов, выполнения действий над ними и формирования адреса инструкций и операндов в памяти. Другая часть регистров используется процессором для служебных (системных) целей, доступ к ним может быть ограничен (есть даже программно-невидимые регистры).
    Память
"расползлась" по многим компонентам. Оперативная память (ОЗУ) - самый большой массив ячеек памяти со смежными адресами - реализуется, как правило, на модулях (микросхемах) динамической памяти. Для повышения производительности обмена данными (включая и считывание команд) оперативная память кэшируется сверхоперативной памятью (см. п. 6.1). Первый, а зачастую и второй уровень кэширования территориально располагается в микропроцессоре. Оперативная память вместе с кэшем всех уровней (теперь даже до трех) представляет собой единый массив памяти, непосредственно доступный процессору для записи и чтения данных, а также считывания программного кода. Кроме оперативной память включает также и постоянную (ПЗУ), из которой можно только считывать команды и данные, и некоторые виды специальной памяти (например, видеопамять графического адаптера). Вся эта память вместе с оперативной располагается в едином пространстве с линейной адресацией. В любом компьютере обязательно есть постоянная память, в которой хранится программа начального запуска компьютера и минимально необходимый набор сервисов (ROM BIOS). Память дополняется устройствами хранения данных, например дисковыми. Эти устройства предназначены для записи данных с целью последующего считывания (возможно, и на другом компьютере). От рассмотренной выше памяти, называемой также внутренней, устройства хранения отличаются тем, что процессор не имеет непосредственного доступа к данным по линейному адресу. Доступ к данным на устройствах хранения выполняется с помощью специальных программ, обращающихся к контроллерам этих устройств.
    Устройства ввода-вывода
(УВВ) служат для преобразования информации из внутреннего представления в компьютере (биты и байты) в форму, доступную окружающим, и обратно. Под окружающими понимаем как людей, так и другие машины (например, технологическое оборудование, которым управляет компьютер). К устройствам ввода относятся клавиатура, мышь, джойстик, микрофон, сканер, видеокамера, различные датчики; к устройствам вывода - дисплей, принтер, плоттер, акустические системы (наушники), исполнительные механизмы. Список устройств ввода-вывода безграничен - благодаря фантазии и техническому прогрессу в него входят все новые и новые устройства; так, например, шлем виртуальной реальности из области фантастики вышел в производственно-коммерческую. Устройства хранения к УВВ относить некорректно, поскольку здесь преобразования информации ради доступности внешнему миру не происходит - что сохранил (неважно, на каком носителе), то и прочитал (если удалось). Устройства хранения вместе с УВВ можно объединить общим понятием периферийные устройства. Существует еще большой класс коммуникационных устройств, предназначенных для передачи информации между компьютерами и(или) их частями. Эти устройства обеспечивают, например, соединение компьютеров в локальные сети или подключение терминала (это УВВ) к компьютеру через пару модемов.
    Периферийные и коммуникационные устройства (и даже память) снабжаются контроллерами или адаптерами, которые доступны процессору. Все компоненты компьютера представляются для процессора в виде наборов ячеек памяти или(и) портов ввода-вывода. Процессор может адресоваться к ним с точностью до одного байта - набора смежных восьми бит. Каждый байт (ячейка памяти, порт) имеет собственный уникальный физический адрес. Этот адрес устанавливается на системной шине процессором, когда он инициирует обращение к данной ячейке или порту. В семействе x86 и PC-совместимых компьютерах пространства адресов ячеек памяти и портов ввода-вывода разделены. Это предусмотрено с обеих сторон: процессоры позволяют, а компьютеры используют данное разделение. В принципе это разделение не обязательно, существуют процессоры, для которых все внешние ячейки рассматриваются только как память. Контроллеры и адаптеры периферийных устройств могут и не использовать порты в пространстве ввода-вывода, если их регистры отображены на пространство памяти. Отображение на память неудобно тем, что для регистров периферийных контроллеров трудно выбрать постоянное место приписки. Оперативную память всегда стремятся представлять в виде единого непрерывного массива ячеек со смежными физическими адресами, следовательно, для регистров можно выделить зону адресов либо до начального адреса ОЗУ, либо после конечного. То и другое плохо: либо из адресов ОЗУ уйдет область, начинающаяся с нулевого адреса (процессоры x86 используют ее для векторов прерываний), либо начало зоны регистров придется отодвинуть очень далеко в область старших адресов, чтобы ее не "достала" оперативная память. Напомним, что за историю PC типовой объем ОЗУ вырос уже на три порядка и подбирается к гигабайту. Семейство x86 стартовало с разрядности шины адреса памяти 20 бит (8086/88), что позволяло адресовать 210 = 1 048 576 ячеек (1 Мбайт). Нынешние процессоры имеют разрядность физического адреса памяти 32 и даже 36 бит, что позволяет адресовать до 4 и 64 Гбайт соответственно. Пространство ввода-вывода использует только младшие 16 бит адреса, что позволяет адресовать до 65 384 однобайтных регистров. Адреса "исторических" системных устройств PC не изменились с самого рождения - это дань совместимости, которая без разделения пространств вряд ли бы просуществовала столько лет. Пространства памяти и ввода-вывода неравнозначны не только по объему, но и по способам обращения. Способов адресации к ячейке памяти в x86 великое множество (см. п. 2.3), в то время как для адресации ввода-вывода их существует только два. К памяти возможна (и широко используется) виртуальная адресация, при которой для программиста, программы и даже пользователя создается иллюзия оперативной памяти гигантского размера. В этом случае реальный физический адрес процессор формирует из логического адреса (указанного программистом) под управлением операционной системы, поддерживающей виртуальную память. Иллюзия большого объема создается операционной системой с помощью устройств хранения и специальных аппаратных средств процессора (см. п. 5.6). Возможна и реальная адресация к памяти - в этом случае физический адрес совпадает с логическим. К портам ввода-вывода обращаются только по реальным адресам, правда, и здесь возможна виртуализация, но уже чисто программными средствами операционной системы. И, наконец, самое существенное различие пространств памяти и ввода-вывода: процессор может считывать инструкции для исполнения только из пространства памяти. Конечно, через порт ввода можно считать фрагмент программного кода (что и происходит, например, при считывании данных с диска), но для того, чтобы этот код исполнить, его необходимо записать в память.
    Процессор исполняет программный код, находящийся к моменту исполнения в пространстве памяти. Программный код - это последовательность команд, или инструкций, каждая из которых определенным образом закодирована и расположена в целом числе смежных байт памяти. Каждая инструкция обязательно имеет операционную часть, несущую процессору информацию о требуемых действиях. Операндная часть, указывающая процессору, где находится его "предмет труда" - операнды, может присутствовать в явном или неявном виде и даже отсутствовать. Операндная часть может описывать от нуля до двух операндов, участвующих в данной инструкции (есть инструкции, в которые кроме двух операндов задается еще и параметр инструкции). Здесь могут быть сами значения операндов (непосредственные операнды); явные или неявные указания на регистры процессора, в которых находятся операнды; адрес ячейки памяти (или его составная часть); регистры процессора, участвующие в формировании адреса, и разные комбинации этих компонентов. Длина инструкции в семействе x86 может быть от одного до 12 байт и определяется типом инструкции. Исторически сложившийся формат инструкций x86 довольно сложен, и "понять", сколько байт занимает конкретная инструкция, процессор может, лишь декодировав ее первые 1-3 байт. Инструкции могут предшествовать префиксы (к счастью, всегда однобайтные), указывающие на изменение способа адресации, размера операнда или(и) необходимость многократного (по счетчику и условию) повторения данной инструкции (см. главу 4). Адрес (логический) текущей исполняемой инструкции хранится в специальном регистре - указателе инструкций (Instruction Pointer, IP), который соответствует счетчику команд фон-неймановской машины. После исполнения так называемой линейной инструкции этот указатель увеличивает свое значение на ее длину, то есть указывает на начало следующей инструкции. Линейная инструкция не нарушает порядок выполнения, определяемый последовательностью расположения инструкций в памяти (по нарастанию адреса). Кроме линейных инструкций существуют инструкции передачи управления, среди которых различают инструкции переходов и вызовов процедур. Эти инструкции в явном или неявном виде содержат информацию об адресе следующей выполняемой инструкции, который может указывать на относительно произвольную ячейку памяти. Инструкции переходов и вызовов могут быть безусловными (ни от чего не зависящими) и условными. Произойдет условный переход (вызов) или нет, зависит от состояния флагов (признаков) на момент исполнения данной инструкции. Если переход (вызов) не состоится, то исполняется инструкция, расположенная в памяти следом за текущей. Вызов процедуры характерен тем, что перед ним процессор сохраняет в стеке (стек - это область ОЗУ) адрес следующей инструкции, и на этот адрес передается управление после завершения исполнения процедуры (этот адрес извлекается из стека при выполнении инструкции возврата). При переходе в стеке ничего не сохраняется, то есть переход выполняется безвозвратно.
    Последовательность исполнения инструкций, предписанная программным кодом, может быть нарушена под воздействием внутренних или внешних (относительно процессора) причин. К внутренним причинам относятся исключения (exceptions) - особые ситуации, возникающие при выполнении инструкций (см. п. 2.5). Наглядным примером исключения является попытка деления на ноль. При возникновении условия исключения процессор автоматически выполняет вызов процедуры обработки исключения, после которой он может вернуться к повторному исполнению инструкции, породившей исключение, или следующей за ней. Вариант поведения зависит от типа произошедшего исключения. Исключения широко используются современными операционными системами, на основе обработки исключений строится система виртуальной памяти и реализуются многие функции многозадачных операционных систем. Внешними причинами изменения нормальной последовательности инструкций являются аппаратные прерывания - вызовы процедур под воздействием электрических сигналов, поступающих на специальные выводы процессора (см. п. 2.5). Эти сигналы могут подаваться совершенно неожиданно для исполняемой программы, правда, у программиста есть возможность заставить процессор (компьютер) игнорировать все прерывания или их часть. Злоупотреблять этой возможностью нельзя (да и не всегда она есть), поскольку на аппаратных прерываниях строится, например, отсчет времени и другие системные и прикладные функции компьютера. Источниками аппаратных прерываний являются контроллеры и адаптеры периферийных устройств, генераторы меток времени, системы управления питанием и другие подсистемы. Есть еще так называемые программные прерывания, но они отнюдь не нарушают последовательность инструкций, предписанную программистом. Поэтому прерываниями они, по сути, не являются - это всего лишь особый способ вызова процедур, широко используемый для вызова системных сервисов BIOS и операционной системы. И наконец, последовательность инструкций может изменяться по сигналу аппаратного сброса или инициализации процессора. С этого, собственно, и начинается функционирование компьютера: процессор переводится в исходное состояние и запускается. При этом указатель инструкций совместно с другими регистрами, участвующими в формировании адреса инструкции, генерирует адрес, на 15 байт меньший максимального физического адреса (у процессоров P6 возможен выбор между значением FFFFFFFF0h и FFFF0h). По этому адресу должна располагаться инструкция, с которой начинается инициализация компьютера.
    Итак, начнем с аппаратного сброса. Во время действия этого сигнала процессор пассивен - он не управляет системной шиной. Процессор подготавливается к работе, воспринимая со своих выводов сигналы, задающие его конфигурацию (коэффициент умножения, роль в многопроцессорных системах и некоторые другие параметры). Внутренний кэш очищается, регистры (не все) приводятся в определенное состояние. После окончания сигнала процессор по определенному адресу (см. выше) выбирает из памяти и исполняет первую инструкцию - управление передается на точку входа в программу инициализации компьютера. Программа инициализации, называемая POST (PowerOn Self Test - самотестирование по включению), хранится в постоянной памяти ROM BIOS (ПЗУ базовой системы ввода-вывода). Первым делом необходимо выполнить инициализацию процессора - установить желаемый режим и значения некоторых регистров. Далее выполняется проверка работоспособности и инициализация подсистем компьютера. Эта "раскрутка" выполняется в несколько этапов, постепенно вовлекая в работу протестированные подсистемы. Поначалу программа может смело пользоваться только регистрами процессора и постоянной памятью, предварительно ее проверив (например, путем подсчета контрольной суммы). Если ПЗУ исправно, можно двигаться дальше, в противном случае лучше остановиться. Пока неизвестна работоспособность ОЗУ, оперативной памятью пользоваться нельзя и, следовательно, недоступны вызовы процедур и обработка прерываний (вызвать-то процедуру можно, а вот возврат не гарантируется, поскольку адрес возврата берется из стека, то есть из ОЗУ). Далее инициализируется ОЗУ (программируются регистры чипсета, управляющие параметрами контроллера памяти и регенерацией) и выполняется тестирование небольшого блока в его начале. Если тест прошел успешно, то для дальнейшей работы можно уже пользоваться вызовами и прерываниями (не забыв проинициализировать таблицу прерываний), а также памятью для хранения переменных - в таком окружении работать гораздо удобнее. Теперь можно проинициализировать и протестировать дисплейный адаптер, - дальнейшая раскрутка пойдет уже с "ожившим" экраном. Далее тестируется ОЗУ в полном объеме, определяется наличие контроллеров и адаптеров, они инициализируются и тестируются. Теперь система BIOS "знает" реальную конфигурацию компьютера и готова к загрузке операционной системы. Векторы прерываний, за которые отвечает BIOS, проинициализированы - ими можно пользоваться. В этот момент можно войти в меню встроенной утилиты конфигурирования - BIOS Setup, которая позволяет изменять настройки различных подсистем компьютера. После окончания работы этой утилиты программу инициализации (POST) приходится выполнять снова - конфигурация может стать уже иной. Программа POST завершается вызовом процедуры начальной загрузки.
    Для процессоров, начиная с шестого поколения, у POST есть дополнительная забота - загрузить "заплатки" микропрограмм самого процессора (update microcode, см. п. 7.2). Эти заплатки позволяют исправить некоторые ошибки, выявленные в процессорах определенных моделей и партий выпуска. Без них основные функции процессор, конечно, выполнять будет, но в современных сложных операционных системах и приложениях, как говорится, возможны варианты. Информация о том, какие заплатки требуются конкретному процессору, и сами заплатки хранятся в ROM BIOS. Если BIOS про установленный процессор (какой именно процессор установлен, POST может определить программно, см. п. 8.2) ничего не "знает", то и заплатки не загрузит. По этой причине может потребоваться обновление версии BIOS, которое на современных системных платах выполняется довольно просто (если производитель своевременно "выкладывает" образ BIOS на своем web-сайте).
    Процедура начальной загрузки
(bootstrap loader) вызывается как программное прерывание (BIOS Int 19h). Эта процедура определяет первое готовое устройство из списка разрешенных и доступных (гибкий или жесткий диск, компакт-диск, сетевой адаптер) и пытается загрузить с него в ОЗУ короткую программу загрузки. Эта программа может выполняться в два этапа: сначала с жесткого диска загружается главный загрузчик MBR (Master Boot Record) и ему передается управление. Главный загрузчик определяет на диске активный раздел, загружает загрузчик этого раздела и передает управление ему. В свою очередь загрузчик активного раздела загружает необходимые файлы операционной системы и передает ей управление. Напомним, что "передать управление" означает выполнить инструкцию перехода на адрес точки входа в программу, загруженную в оперативную память. Операционная система выполняет инициализацию подведомственных ей программных и аппаратных средств. Она добавляет новые сервисы, вызываемые, как правило, тоже через программные прерывания, и расширяет некоторые сервисы BIOS. Под управлением операционной системы загружаются и исполняются пользовательские приложения и разные вспомогательные процессы и утилиты. Операционная система ведает распределением всех ресурсов компьютера - памяти (как оперативной, так и пространства на устройствах хранения данных), процессорного времени (в многозадачных системах), периферийных и коммуникационных устройств. Она же предоставляет интерфейс пользователя, с помощью которого запускаются приложения, настраиваются параметры ОС и выполняются иные действия пользователя. По окончании работы современные ОС требуют корректного закрытия (shutdown) - завершения работы приложений и сохранения информации, необходимой пользователю и операционной системе, на энергонезависимых носителях (на диске). Только после этого компьютер можно выключать или выполнять аппаратный сброс кнопкой Reset. Если выключить или сбросить компьютер (в смысле нажать кнопку Reset) до выполнения операций завершения, могут появиться проблемы при последующей загрузке: потеря несохраненных данных (пользовательских или системных настроек), потеря фрагментов дисковой памяти (кластеров) и даже разрушение ОС, требующее ее переустановки. Компьютеры в конструктиве ATX "умеют" сами выключать питание по завершении работы ОС, что упрощает правила поведения пользователя.
    После этого беглого описания цикла работы компьютера (от включения до выключения) чуть подробнее остановимся на таких моментах, как прерывания, защищенный режим, многозадачность, виртуальная память.
    Процессор фон-неймановской машины фактически может выполнять только один процесс, передавая управление от инструкции к инструкции согласно исполняемой программе. При этом могут исполняться переходы, ветвления и вызовы процедур, но вся эта цепочка запрограммирована разработчиком программы. Теперь рассмотрим случай, когда во время этого процесса случается асинхронное по отношению к процессу событие, требующее реакции компьютера. Для примера рассмотрим нажатие клавиши на клавиатуре. Клавиатура (это устройство ввода) по нажатию (как и отпусканию) любой клавиши по своему интерфейсу генерирует специальное сообщение, содержащее код этого события (скан-код клавиши). Контроллер клавиатуры, находящийся на системной плате, принимает этот код в свой внутренний регистр и сигнализирует об этом двумя способами: устанавливает флаг готовности (бит в регистре состояния, который может быть прочитан процессором по адресу известного порта ввода) и генерирует сигнал запроса прерывания (сигнал IRQ1). Этот сигнал поступает на вход контроллера прерывания - системного устройства, обслуживающего запросы от множества линий (о дисциплине обслуживания здесь говорить не будем). Контроллер прерываний формирует сигнал запроса, поступающий на вход маскируемого прерывания процессора (сигнал INTR). Если у процессора маскируемые прерывания разрешены, то он запросит у контроллера номер вектора прерывания, соответствующего данному источнику прерывания. В нашем случае (сигнал от клавиатуры) это будет вектор 9. Получив значение вектора, процессор сохранит в стеке адрес следующей инструкции исполняемого процесса и выполнит вызов процедуры обработки прерывания, адрес которой задан в 9-м элементе таблицы прерываний. В нашем компьютере эта процедура считает скан-код из контроллера клавиатуры (в ответ он сбросит бит готовности в своем регистре состояния), выполнит минимально необходимые действия, связанные с получением этого кода, и некоторые манипуляции с контроллером прерываний, позволяющие ему правильно реагировать на последующие запросы прерываний. Процедура обработки прерывания завершается специальной инструкцией возврата (IRET), по которой управление вернется прерванному процессу. Кроме маскируемых прерываний есть и немаскируемое прерывание с фиксированным вектором 2, для которого у процессора имеется отдельный вход NMI, а также системное прерывание SMI. Нюансы обработки прерываний процессором рассмотрены в п. 2.5. Альтернативой прерываниям для реакции на асинхронное событие может быть программный опрос готовности УВВ - полинг. Чтобы обеспечить реакцию на асинхронное событие, исполняемый процесс в нашем случае должен периодически опрашивать (читать из порта ввода) регистр состояния контроллера клавиатуры и, если будет замечен установленный флаг готовности, исполнять процедуру обработки данного события. Непригодность такого подхода в данном случае вполне очевидна - любой процесс, во время которого требуется реакция на асинхронное событие (а самому процессу это событие может быть и безразлично), должен быть загроможден периодическими вставками программного кода опроса готовности. Кроме "лохматого" вида самой программы, на опрос тратится процессорное время, и в основном бесполезно (клавиши нажимают не так уж часто). Если опрос производить редко, то время реакции на событие может недопустимо возрасти. Прерывания могут использоваться и в сочетании с полингом: процесс опроса готовности (возможно, нескольких устройств) периодически запускается по прерываниям от системного таймера.
    Прерывания используют и для переключения задач в многозадачных системах (см. п. 5.5). Пусть, например, имеются два процесса (грубо говоря, две прикладные программы), которые должны выполняться как бы одновременно (по-настоящему одновременно один фон-неймановский процессор их выполнить не может). Можно запустить один процесс, а через некоторое время его работы по аппаратному прерыванию (от таймера) сохранить в памяти контекст задачи - образ ее текущего состояния (все регистры, программно-доступные этому процессу) и запустить другой процесс. Через некоторое время по следующему прерыванию выполнить обратное переключение контекста: сохранить состояние второго процесса (в другом месте памяти), загрузить в регистры процессора образ состояния первого процесса и продолжить его выполнение. Эти переключения задач следует выполнять с частотой, создающей у пользователя иллюзию непрерывности и одновременности исполнения обеих программ. Понятно, что ресурсы процессора (производительность) в этом случае делятся между задачами пропорционально выделяемым им квантам времени. Чтобы пользователя такая производительность процессов удовлетворяла (а еще учтем накладные расходы на сохранение и восстановление образов при переключениях), у процессора должна быть достаточная мощность. Процессоры семейства x86, начиная со второго и, особенно, с третьего (386) поколения, имеют встроенные средства многозадачности (число задач почти не ограничено), работающие в защищенном режиме. Переключение задач производится по сигналу прерывания от таймера совершенно "прозрачно" для процессов, работающих псевдопараллельно. Благодаря этой прозрачности программисту, разрабатывающему прикладную программу, в большинстве случаев не надо заботиться о реализации многозадачной работы. В распоряжение его программы предоставляется виртуальная машина (тоже фон-неймановская), в которой управление передается последовательно этой программой, как будто она - единственный процесс. Конечно, поддержка виртуальных машин требует определенных усилий со стороны многозадачной операционной системы, которой приходится распределять не только процессорное время, но и память, устройства хранения, ввода-вывода и коммуникационные устройства - то есть все ресурсы реального компьютера. В этом ей помогают специальные средства, введенные в процессоры x86 2-3-го поколений и постоянно развиваемые в следующих поколениях.
    Чтобы процессы не мешали друг другу (по недосмотру или умышленно), требуются меры принудительной защиты критически важных ресурсов. Современные операционные системы используют защищенный режим процессора, в котором эти меры реализуются на аппаратном уровне. Поскольку программа может взаимодействовать с подсистемами компьютера только через пространства памяти и портов ввода-вывода, а также аппаратные прерывания, то защищать нужно эти три типа ресурсов. Самую сложную защиту имеет память. Операционная система выделяет каждому процессу области памяти - сегменты - различного назначения и с разными правами доступа. Из одних сегментов можно только читать данные, в другие возможна и запись. Для программного кода выделяются специальные сегменты, инструкции могут выбираться и исполняться только из них. По отношению к принципу хранимости программы это является искусственным ограничением для фон-неймановской машины, но его целесообразность очевидна. Процессору "безразлично" содержимое ячейки памяти, на которую передано управление, - он всегда пытается трактовать ее как код инструкции (или префикс). Если ошибочно управление передано на область данных, то дальнейшее поведение процессора непредсказуемо - это так называемый "вылет". Защита не позволяет передать управление на сегмент данных - сработает исключение защиты, которое обрабатывается операционной системой, и ошибочный процесс будет принудительно завершен. Таким образом, вероятность вылета уменьшается. Чтобы выдержать принцип хранимости программы, на время ее загрузки в память или на время программной модификации ту же область объявляют и сегментом данных, в который разрешена запись. Система защиты может полностью контролировать распределение памяти, генерируя исключения в случаях различных нарушений. Конечно же, эффективность защиты (устойчивость компьютера к ошибкам) в значительной мере определяется предусмотрительностью разработчиков операционной системы. Средства распределяемости и защиты памяти, ввода-вывода и прерываний подробно описаны в главе 5.
    Чем сложнее программа и больше объем обрабатываемых ею данных, тем больше ее потребности в памяти. В первых процессорах семейства память предоставлялась в виде сегментов размером по 64 Кбайт, а суммарный объем программно адресуемой памяти ограничивался размером 1 Мбайт. Архитектура PC ограничивала размер оперативной памяти объемом в 640 Кбайт, начиная с нулевых адресов. Эта область называется стандартной памятью (conventional memory), и для прикладных программ из нее остается доступной область порядка 400-550 Кбайт (остальное "съедает" операционная система вместе с разными драйверами). Потребности решаемых задач довольно быстро переросли эти ограничения, и в процессоры ввели средства организации виртуальной памяти. Впервые они появились в модели 80286, но удобный для употребления вид приняли только в 32-разрядных процессорах (80386 и выше). Во-первых, было снято ограничение на размер сегмента в 64 Кбайт - теперь любой сегмент может иметь почти произвольный размер до 4 Гбайт. Во-вторых, был введен механизм страничной переадресации памяти (paging, см. п. 5.6). Теперь любая страница (область фиксированного размера) виртуальной логической памяти (адресуемой программой в пределах выделенных ей сегментов) может отображаться на любую область физической памяти (реально установленной оперативной). Отображение поддерживается с помощью специальных таблиц страничной переадресации, в которых кроме связи адресов есть указание на присутствие страницы в физической памяти на данный момент времени. Теперь страница памяти, не нужная процессору в данный момент времени, может быть выгружена на устройство хранения (диск), а на ее место, при необходимости, загружена нужная страница. Заявку на загрузку нужной страницы делает сам процессор, без каких-либо усилий выполняемой программы: если программе потребовалась ячейка виртуальной памяти из страницы, образа которой сейчас нет в физической памяти, вырабатывается специальное исключение. Обработчик этого исключения (это часть ОС) найдет свободную физическую страницу (выгрузив на диск ту, которая, по его мнению, пока не нужна), "подкачает" на нее с диска требуемую информацию и вернет управление процессу, прерванному исключением. Сам процесс ничего "не заметит" (кроме некоторой задержки в выполнении инструкций). Таким образом, в распоряжение всех процессов, исполняемых на компьютере псевдопараллельно, предоставляется виртуальная оперативная память, размер которой ограничен суммой объема физической оперативной памяти и областью дисковой памяти, выделенной для подкачки страниц. Процесс подкачки (замещения) страниц называется свопингом (swaping), а области дисковой памяти, выделяемые для этих целей, - файлами подкачки, или своп-файлами (swap file). Прикладной вывод из этих рассуждений: если на компьютере перестают запускаться приложения, что сопровождается сообщениями о недостаточном объеме оперативной памяти, - проверьте наличие свободного места на жестких дисках, используемых для подкачки. Этот вывод, естественно, относится только к операционным системам защищенного режима (Windows, UNIX, OS/2 и т. д.).
    Теперь вернемся к исполнению инструкций обработки данных - инструкций выполнения арифметических или логических функций. Во многих случаях инструкция работает с парой операндов - операндом назначения dest (destination) и операндом-источником src (source). Традиционная схема действия инструкции: dest = F(dest, src), где F - некоторая функция от двух переменных. Это означает, что при выполнении инструкции процессор извлекает из указанных в инструкции мест (регистр, память, константа в самой инструкции) пару двоичных чисел и результат действия над ними записывает на место одного из них (dest). Для выполнения той же функции над следующей парой чисел требуется повторное исполнение инструкции, но уже с другой парой операндов. Такой принцип исполнения естественен для базовой архитектуры процессоров x86. В процессоры Pentium, "под занавес" их развития, было введено расширение MMX, направленное на ускорение обработки потоков и массивов данных (см. п. 3.2). Ключевым в этом расширении стал принцип SIMD (Simple Instruction - Multiple Data, одна инструкция на множество данных). Здесь вводятся новые упакованные форматы данных: в один регистр MMX можно помещать не только один операнд (64-битное число), но и пару 32-битных, четверку 16-битных или восьмерку 8-битных чисел. Одна инструкция MMX выполняет однотипные действия сразу над всеми числами, упакованными в регистры MMX, заданные операндной частью данной инструкции. Поначалу набор инструкций MMX ограничивался целочисленной арифметикой и логикой, и он стал стандартом для всех современных процессоров x86. Позже появились расширения 3DNow! (от AMD) и SSE (от Intel) для чисел в формате с плавающей точкой, сильно различающиеся по набору инструкций.
    Несколько слов о числах с плавающей точкой. Архитектура процессора 8086 позволяет выполнять арифметические функции (сложение, вычитание, умножение и деление) над целочисленными данными (знаковыми и беззнаковыми, двоичными и двоично-десятичными) разрядностью 8 или 16 бит. В процессорах 386+ можно обрабатывать и 32-разрядные числа. Для работы с числами в формате с плавающей точкой (представленными в виде мантиссы и порядка) предусмотрен математический сопроцессор. Сопроцессор представляет собой набор 80-битных регистров и специализированное арифметическое устройство, которое кроме четырех арифметических действий способно вычислять значение квадратного корня, тригонометрических функций, логарифмов и степеней чисел. Сопроцессор может только перехватывать адресованные ему инструкции из потока команд, выполняемых центральным процессором, а все манипуляции с памятью выполняет центральный процессор. Сложные функции сопроцессора требуют дово
Календарь
«  Апрель 2024  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Copyright MyCorp © 2024
    Конструктор сайтов - uCoz