Ранее в общих чертах было рассмотрено устройство компьютера (естественно, подразумевается наличие корпуса с блоком питания). Однако этот набор «железок» не имеет практической ценности без программного обеспечения (ПО), которое в компьютере имеет многоуровневую организацию.
Неотъемлемой от компьютера частью программного обеспечения является базовая система ввода-вывода (Basic Input-Output System, BIOS), которая хранится в постоянной (энергонезависимой) памяти ROM BIOS (ПЗУ базовой системы ввода-вывода). В ROM BIOS находится программа инициализации, называемая POST (PowerOn Self Test — самотестирование по включению), которая обеспечивает тестирование и запуск компьютера при включении, а также загрузку операционной системы. В ROM BIOS содержатся процедуры для работы со стандартными устройствами, реализующие связь операционной системы и прикладных программ с аппаратными средствами компьютера. BIOS предоставляет такие сервисы, как ввод символа с клавиатуры, вывод на экран или принтер, чтение-запись сектора на диске и ряд других (см. главу 5). BIOS находится на самым нижнем уровне ПО, который обеспечивает изоляцию вышестоящих уровней от подробностей реализации аппаратных средств компьютера. В ROM BIOS имеется также утилита CMOS Setup, обеспечивающая настройку аппаратных средств компьютера.
Следующий уровень — операционная система (ОС), основным назначением которой является загрузка прикладных программ и предоставление им некоторых сервисов. Сервисы ОС функционируют на более высоком уровне — если BIOS работает с физическими устройствами, то ОС предоставляет возможность работы на логическом уровне. Сервисы ОС, обслуживающие стандартные устройства, могут обращаться к соответствующим сервисам BIOS; они расширяют функциональность сервисов BIOS, а также выполняют обработку ошибок физических устройств. ОС может работать с системными устройствами и в обход BIOS, через собственные драйверы. В MS-DOS все сервисы ОС обслуживались через BIOS, что обеспечивало высокий уровень совместимости и переносимости ПО с машины на машину, но ценой невысокой эффективности. Более современные ОС работают в обход BIOS — это эффективнее с точки зрения производительности, но осложняет переносимость ПО. ОС ведает распределением системных ресурсов. На устройствах хранения она организует файловую систему. Операционная система, как правило, загружается с устройства внешней памяти (локального или сетевого диска), хотя для специальных применений (во встроенных компьютерах) встречаются и так называемые резидентные ОС, «зашитые» в ПЗУ. Для загрузки ОС требуется специально подготовленный системный диск. В самом начале системного диска располагается загрузчик — короткая программа, загружающая несколько файлов ядра операционной системы в память и передающая им управление. Эти файлы находятся на том же системном диске в месте, известном загрузчику (он должен найти файлы еще до того, как будет обеспечена поддержка файловой системы со стороны ОС). Программный код загрузчика привязан к загружаемой ОС и файловой системе диска, но сам загрузчик для любых ОС и дисков запускается единым способом (см. 9.6). Если загрузчик на своем диске находит необходимые файлы операционной системы (например, IO.SYS и MSDOS.SYS), он загружает их в оперативную память и передает управление по определенному адресу. С этого момента работой компьютера управляет ОС, она загружает все свои компоненты, выполняет нужные настройки и подготавливается для загрузки и исполнения приложений, предоставляя им сервисы файловой системы (см. 9.11). Естественно, чем сложнее ОС, тем больший объем памяти ей требуется. Первые ОС помещались на гибких дисках небольшого объема (180 Кбайт) и довольно быстро с них загружались. ОС Windows (и другие современные ОС) занимают десятки (а то и сотни) мегабайт и загружаются довольно долго (минуты) даже на самых быстрых ПК. Но, к счастью, на гибком диске вполне умещается минимальный вариант ОС, достаточный для «понимания» файловой системы Windows и запуска приложений и утилит восстановления. Так что на случай аварии «большой» ОС можно иметь «спасательную» дискету, достаточную для начала «аварийно-спасательных работ». И наконец, верхний уровень иерархии ПО — прикладное программное обеспечение, ради исполнения которого и «городился весь этот огород». Прикладные программы могут пользоваться сервисами ОС, BIOS, а также обращаться к аппаратным средствам компьютера напрямую, адресуясь к портам и ячейкам памяти. Чем ближе прикладная программа к «железу», тем эффективнее она может с ним работать (вызовы сервисов BIOS, а тем более ОС вносят дополнительные накладные расходы на организацию программных интерфейсов). Однако использование сервисов высокого уровня (BIOS, а тем более ОС) страхует от возможных проблем совместимости программного обеспечения с аппаратными средствами компьютера. Прикладные программы, как и ОС как правило, загружаются с устройств внешней памяти. Именно возможность загрузки любой прикладной программы в совокупности с неограниченным ассортиментом подключаемых устройств и позволяет считать персональный компьютер универсальным инструментом с неограниченными возможностями.
Важными компонентами программного обеспечения являются драйверы (driver — буквально, «водитель») — программные модули, содержащие процедуры работы с устройствами. Необходимость выделения драйверов в отдельные модули вполне очевидна: устройство определенного назначения (к примеру, дисплейный адаптер) может иметь самые разные реализации — от MDA до современных видеокарт с трехмерными акселераторами. Если бы не было драйверов, то программист, разрабатывающий прикладную программу, должен был бы включать в нее множество аппаратно-зависимых процедур, причем для всех известных ему моделей дисплейных адаптеров. На написание этих процедур он потратил бы массу времени, программа неимоверно «распухла» бы, а появление новых дисплейных адаптеров потребовало бы модернизации прикладной программы. К этому добавим еще и богатые возможности для ошибок (надо заметить, что ошибки на стыке программ и «железа» довольно трудно «ловить»). Выделение драйверов в отдельные модули избавляет от этих и других неудобств. Драйвер хорошо «знает» программную модель и особенности эффективной работы со своим устройством. Для прикладных программ или операционной системы драйвер представляет набор сервисов с интерфейсом, понятным «потребителю». Для каждого сервиса известны способ вызова (программное прерывание или точка входа в процедуру), а также местоположение входных и выходных данных. Если говорить о дисплейных адаптерах, то базовые сервисы (например, очистка экрана, вывод символа в определенную позицию в телетайпном режиме) вызываются через прерывание Int 10h, которое обслуживает BIOS, а параметры передаются через регистры процессора. В зависимости от типа установленного дисплейного адаптера этот сервис обслуживается либо системной микросхемой BIOS, либо микросхемой ROM BIOS, расположенной на графической карте (см. главу 10). Драйверы, обслуживающие данный сервис, специально загружать не требуется — они подставляются автоматически на этапе инициализации BIOS. Однако более сложные сервисы графической карты, которыми, например, пользуется ОС Windows, реализуются отдельными загружаемыми драйверами, «предъявляемыми» на этапе установки ОС. Плохой драйвер может быть источником самых разных неприятных эффектов, вплоть до «зависания» компьютера и даже разрушения ОС. А если речь идет о драйвеpax устройств хранения, то под угрозой оказываются и файлы, хранящиеся на этих устройствах. Плохие драйверы часто появляются из-за желания производителей побыстрее выпустить новый продукт, пускай даже в еще «сыром» виде. Качественный драйвер работает без побочных эффектов, а очень качественный — еще и быстро. Хорошим тоном для производителей устройств является поддержка своих изделий для постоянно меняющихся версий операционных систем и прикладных программ. К сожалению, некоторые модели со временем оказываются заброшенными, и их не удается использовать с новыми продуктами не потому, что последние для них непригодны, а только из-за отсутствия нужного драйвера.