Операционная система OS/2 Warp© Александр Фролов, Григорий ФроловТом 20, М.: Диалог-МИФИ, 1993, 271 стр. 1.1. Состав и особенности IBM OS/2 WarpОперационная система IBM OS/2 Warp, в отличие от Microsoft Windows и Microsoft Windows for Workgroups, является полнофункциональной, т. е. для ее работы не требуется DOS. Она устанавливается в отдельный раздел жесткого диска или в раздел DOS (по усмотрению пользователя). После загрузки IBM OS/2 Warp получает полный контроль над аппаратным и программным обеспечением компьютера, что значительно повышает надежность системы по сравнению с тандемом "DOS - Microsoft Windows". Ядро IBM OS/2 Warp, как и ядро всякой другой полнофункциональной операционной системы, содержит весь набор компонент, или систем, необходимых для решения таких задач, как обеспечение доступа к дискам, управление памятью, запуск программ, организация межпрограммного взаимодействия, организация интерфейса с пользователем и т. д. Рассмотрим кратко особенности основных систем. Более подробное описание вы найдете в соответствующих главах этой и следующих книг серии "Библиотека системного программиста", посвященных операционной системе IBM OS/2 Warp. МультизадачностьОперационная система IBM OS/2 Warp по-настоящему является мультизадачной, причем в отличие от Microsoft Windows в OS/2 используется так называемая вытесняющая (preemptive) мультизадачность. Сегодня уже, наверное, излишне подробно описывать те преимущества, которые дает мультизадачность, однако мы все же сделаем некоторые замечания по этому поводу. Как правило, пользователю нужно работать одновременно с несколькими программами. Например, при подготовке текстового документа или в процессе работы с базой данных может возникнуть необходимость отправить или принять факс, поискать что-нибудь в справочной базе данных или просто посчитать на калькуляторе. Поэтому возможность переключения программ имеет очень большое значение. Переключение программПользователи DOS активно работают с резидентными программами, организующими "переключательную" мультизадачность. Как вы знаете, резидентная программа активизируется в том случае, когда пользователь нажимает определенную для каждой резидентной программы комбинацию клавиш. В этом случае выполнение текущей программы приостанавливается, и на экране появляется резидентная программа. Такое переключение программ "вручную" (показанное схематически на рис. 1.1) позволяет пользователю легко приступить к работе с другой программой, не завершая текущей, и затем вновь вернуться к прерванной программе.
Рис. 1.1. "Ручное" переключение программ в DOS В операционную систему MS-DOS версии 5.0 был встроен специальный переключатель программ DOS Shell, который позволял запускать одновременно несколько обычных (не резидентных) программ DOS и переключаться между ними с помощью удобной диалоговой оболочки. Однако переключатель DOS Shell не прижился в MS-DOS, так как был вытеснен Microsoft Windows. MS-DOS версии 6.22 поставляется уже без этого переключателя. И резидентные программы, и переключатель задач не обеспечивают реальной мультизадачности, так как пока одна из запущенных программ работает, другие находятся в "замороженном" состоянии. Поэтому в среде DOS вы едва ли сможете одновременно редактировать текст и принимать факс либо файл через факс-модем, не говоря уже о том, чтобы продолжать работу одновременно с форматированием дискет. Если вам когда-либо приходилось форматировать большое количество дискет в среде DOS, то вы знаете, что во время этой весьма длительной процедуры пользователь может только беспомощно смотреть на экран и слушать щелканье головок НГМД. Невытесняющая мультизадачность Microsoft WindowsОперационные системы Microsoft Windows версии 3.1 и Microsoft Windows for Workgroups версии 3.11 в некоторой степени решают проблему одновременного использования нескольких программ, организуя невытесняющую (nonpreemptive) мультизадачность, которую еще называют "добровольной" мультизадачностью. Суть невытесняющей мультизадачности заключается в том, что операционная система не выполняет принудительного переключения одновременно запущенных приложений Microsoft Windows, например, по прерыванию таймера, но приложения время от времени передают друг другу управление по своей инициативе (рис. 1.2). Это уже лучше чем "переключательная" мультизадачность, но вот вопрос: может ли программист как ни будь вмешаться в этот процесс, правильно распределив приоритеты приложений?
Рис. 1.2. Приложения Microsoft Windows периодически и по своей инициативе передают друг другу управление К сожалению, ни пользователь, ни программист, создающий приложения для Microsoft Windows, не может изменять приоритет приложений Windows (хотя пользователь может изменить приоритеты программ DOS, работающих в среде Microsoft Windows). Дело здесь в том, что для каждой программы DOS операционная система Microsoft Windows создает отдельную виртуальную машину, но все приложения Windows работают на одной системной виртуальной машине. При этом пользователь может изменять приоритеты отдельных виртуальных машин, но не может изменять приоритет приложений Windows, работающих в рамках одной виртуальной машины. Фактически виртуальные машины Microsoft Windows работают в режиме вытесняющей мультизадачности. При этом каждая виртуальная машина получает для работы квант времени. Системная виртуальная машина Microsoft Windows в этом плане ничем не отличается от виртуальных машин, которые используются для работы программ DOS. Поэтому приложения Windows, добровольно разделяя между собой кванты времени, выделенные системной виртуальной машине, сами по себе работают в режиме невытесняющей мультизадачности. Чем это плохо? Потенциально невытесняющая мультизадачность может привести к "зависанию" Microsoft Windows в результате запуска плохо отлаженного приложения, которое не собирается "делиться" ресурсами с другими приложениями. В результате пользователь часто бывает вынужден выполнять перезагрузку компьютера, что не всегда приемлемо. Вытесняющая мультизадачность IBM OS/2В ядро операционной системы OS/2 встроена система разделения времени, выделяющая каждой запущенной программе или приложению кванты времени (рис. 1.3).
Рис. 1.3. Программы OS/2 работают под контролем системы разделения времени Кванты времени выделяются по прерыванию таймера, поэтому вне зависимости от состояния запущенных программ ни одна программа не будет обделена вниманием операционной системы. Такая мультизадачность называется вытесняющей (preemptive). Она реализована не только в IBM OS/2, но и в Microsoft Windows-95, Microsoft Windows NT, а также в различных версиях UNIX. Работоспособность систем с вытесняющей мультизадачностью в целом меньше зависит от работоспособности отдельных приложений, хотя плохо сделанные приложения могут повлиять на производительность всей системы (но не вывести ее из строя). Самая замечательная возможность, предоставляемая системой разделения времени и системой управления программами IBM OS/2 - возможность создания мультизадачных программ и приложений. Уточним, что мы имеем в виду под мультизадачной программой. Для этого вначале вспомним однозадачные программы. Если вы программировали для DOS, то имели дело как раз с линейными однозадачными программами, работающими в однозадачной операционной системе. Программа DOS выполняется линейно, вызывая по мере необходимости различные подпрограммы, функции, а так же прерывания DOS и BIOS (рис. 1.4).
Рис. 1.4. Линейная однозадачная программа В приведенном на рис. 1.4 примере программа получает некоторые данные, обрабатывает их и затем выполняет печать данных и результата обработки на принтере. Все эти действия выполняются строго последовательно, так как пока данные не получены, их нельзя обрабатывать, а пока они не обработаны - печатать. Теперь допустим, что обработка данных, выполняемая функцией Calculate - длительный процесс, занимающий, скажем, 10-20 часов. Такие времена - не редкость при решении задач, например, численного моделирования физических процессов (даже при использовании современных компьютеров). Если эта программа работает в однозадачной операционной системе, компьютер недоступен для решения других задач все время, пока работает функция Calculate. Операционная система Microsoft Windows позволяет вам одновременно запустить несколько различных приложений или несколько копий одного и того же приложения. Поэтому теоретически вы можете попробовать запустить длительную расчетную задачу и еще несколько приложений. Однако из-за невытесняющего характера мультизадачности без принятия специальных мер функция Calculate передаст управление другим приложениям только тогда, когда все расчеты будут завершены (т. е. на следующий день). Конечно, можно составить функцию Calculate таким образом, что она будет выполнять расчет маленькими порциями, разрешая работу других приложений. Однако это требует специальных усилий и не гарантирует полного успеха, так как расчетные задачи отнимают много процессорного времени. В результате другие приложения будут работать так медленно, что воспользоваться ими так и не удастся. Дело можно поправить только в том случае, если регулировать степень использования процессора для работы всех одновременно запущенных программ, т. е. управлять приоритетами программ. Однако для приложений Microsoft Windows это невозможно. Операционная система IBM OS/2 позволяет организовать параллельное выполнение многих программ, а также отдельных фрагментов кода одной и той же программы. Когда пользователь запускает программу в среде IBM OS/2, операционная система создает так называемый процесс (process). Это понятие мы уточним позже, а сейчас достаточно знать, что для процесса выделяется отдельное адресное пространство, изолированное от адресных пространств других процессов. Изоляция выполняется на физическом уровне с использованием схемы адресации памяти защищенного режима (описанной нами в 6 томе "Библиотеки системного программиста"). В рамках процесса создается задача (thread), которая выполняется автономно и асинхронно по отношению ко всем остальным активным задачам. После запуска эта задача может создать в рамках процесса другие задачи. Что такое задача? Задача больше всего похожа на подпрограмму, которая вызывается из основной программы, но выполняется по отношению к ней асинхронно. Это возможно благодаря системе разделения времени, которая передает управление всем активным задачам по прерыванию таймера и с учетом приоритетов задачи. Все задачи, созданные в рамках одного процесса, используют общее адресное пространство процесса. Заметим, что операционная система IBM OS/2 присваивает приоритеты не процессам, а задачам. Поэтому программист не может изменить приоритет процесса (такое понятие, как приоритет процесса просто не существует), но может управлять приоритетом отдельных задач. Синхронизация задачПри использовании параллельно работающих задач возникает проблема синхронизации их выполнения. Изменим немного программу, показанную на рис. 1.4. С помощью гипотетической функции Start запустим подпрограммы PlayMusic и Calculate как задачи в рамках одного процесса (рис. 1.5). Мы постараемся составить программу так, чтобы одновременно с вычислениями она делала что-нибудь еще, например, играла музыку.
Рис. 1.5. Запуск двух задач, первая из которых играет музыку, а вторая выполняет длительные вычисления Теперь после получения данных одновременно выполняется проигрывание музыки и сложный расчет. Но вот вопрос - что сделает функция Start, после того как будет запущена задача, имя которой передается ей в качестве параметра? Если составить эту функцию таким образом, чтобы она дожидалась завершения выполнения запускаемой ей задачи, то пользователь вначале прослушает музыкальное произведение, а затем компьютер приступит к многочасовому расчету. После завершения расчета начнется печать. То есть все осталось, как и раньше. Если же функция Start вернет управление сразу после запуска задачи, то вначале заиграет музыка, а потом на фоне музыки будет запущен расчет. Но тут нас поджидает другая неприятность - сразу после запуска расчета принтер начнет печать, не дожидаясь, пока задача Calculate подготовит необходимые для этого данные. Операционная система IBM OS/2 допускает оба варианта запуска задач, обеспечивая дополнительно такие средства синхронизации задач, как критические секции и семафоры. Критические секцииПрограммист может организовать внутри задачи фрагмент кода, который должен выполняться в монопольном режиме по отношению ко всем другим задачам создавшего их процесса. Такой фрагмент кода и называется критической секцией. Он ограничен сверху и снизу вызовом, соответственно, функций DosEnterCritSec и DosExitcritSec , не имеющих параметров: // Начало критической секции DosEnterCritSec(); ... // Этот фрагмент задачи выполняется в монопольном // режиме по отношению к другим задачам процесса ... // Конец критической секции DosExitcritSec(); По своей сути критические секции предназначены для временной отмены мультизадачности в рамках одного процесса, поэтому в нашем случае с проигрыванием музыки на фоне выполнения расчета само по себе это несложное в использовании средство ничего не даст. Обычно критические секции используются для организации доступа к таким ресурсам, которые можно использовать только последовательно. Представьте себе, например, что вы подключили к компьютеру нестандартное печатающее устройство, для печати на котором необходимо обращаться к портам специализированного контроллера. Если несколько задач, принадлежащих одному или разным процессам, начнут одновременную печать, это может привести к повреждению контроллера или принтера (со стандартным принтером ничего подобного произойти не может, так как IBM OS/2 выполняет все необходимые действия по синхронизации доступа). СемафорыСемафоры в IBM OS/2 по своему назначению напоминают одноименные сооружения, которые вы видели на железной дороге. Их задача - организация правильной последовательности выполнения задач. Так же как отсутствие семафора на железнодорожном переезде может привести к катастрофе, так и неконтролируемый доступ параллельно работающих задач к тем или иным ресурсам может привести к аварийному завершению работы программы, а то и к выходу из строя всей операционной системы. По запросу задачи операционная система может создать один или несколько семафоров, пригодных для синхронизации задач, выполняющихся в рамках одного или разных процессов. При создании семафора ему присваивается идентификатор, который используется во всех последующих операциях, выполняемых над семафором. Не вдаваясь пока в подробности, скажем, что семафор IBM OS/2 можно представить себе как объект, способный находиться в двух состояниях: установленном и сброшенном. При помощи специальных функций задача может переключать семафоры из одного состояния в другое, а также выполнять ожидание момента времени, когда семафор будет переключен другой задачей. Если вам нужна аналогия, представьте себе все тот же железнодорожный переезд и цепочку автомобилей (задач), ожидающих переключения семафора. Теперь мы опять вернемся к нашему "музыкальному" расчету. Попробуем организовать синхронизацию задач Calculate и PrintAll с использованием семафора. Для этого в основной задаче, которая получает управление при запуске процесса, создадим семафор и сразу сбросим его. Затем после ввода данных запустим процесс PlayMusic, Calculate и PrintAll. В самом начале процесса PrintAll вызовем специальную функцию из программного интерфейса IBM OS/2, выполняющую ожидание семафора. Если семафор сброшен (а сразу после запуска задачи PrintAll так оно и есть), задача PrintAll приостановит свое выполнение и перейдет в состояние ожидания. В этом состоянии она не загружает процессор и не мешает работать другим задачам. После выполнения расчетов задача Calculate устанавливает семафор и завершается, разрешая, таким образом, печать результатов расчета. Как только семафор окажется в установленном состоянии, задача PrintAll выйдет из состояния ожидания и начнет свою работу. Что же касается задачи PlayMusic, то она все еще работает. Эту задачу можно остановить либо из задачи PrintAll после выполнения печати, либо из основной задачи. Итак, с помощью семафоров нам удалось организовать синхронизацию нескольких задач. Отметим, что в составе программного интерфейса IBM OS/2 имеется набор удобных в использовании функций, предназначенных для работы с задачами и семафорами. Задача может создать семафоры трех типов, с помощью которых можно организовать ожидание одного или нескольких событий, а также организовать последовательное использование ресурсов, к которым невозможен одновременный доступ со стороны нескольких задач. Каналы передачи данных между процессамиКак мы уже говорили, при запуске программы операционная система создает новый процесс, имеющий изолированное адресное пространство. Изоляция повышает надежность системы, так как ни в результате ошибки, ни намеренно один процесс не сможет адресовать память другого процесса. Однако полностью изолированные процессы не смогут обмениваться данными через оперативную память, что очень неудобно. Конечно, один процесс может подготовить данные для другого процесса в виде файла на диске, но этот способ передачи данных хотя и работает, но слишком медленно. Система управления памятью IBM OS/2 позволяет создавать совместно используемые области памяти (shared memory), которые, в принципе, можно использовать для организации передачи данных между процессами. Однако такой способ требует использования средств синхронизации задач и не пригоден для передачи данных между процессами, запущенными на разных рабочих станциях локальной сети. В операционной системе IBM OS/2 предусмотрено специальное средство передачи данных между различными процессами - каналы (pipes ). Канал - это специальная область памяти, созданная операционной системой по запросу процесса специально для передачи данных между процессами. Канал может иметь имя (а может и не иметь). Работа с каналом больше всего напоминает работу со стандартным потоком ввода или вывода в операционной системе DOS. Процесс создает канал, вызывая специально предназначенную для этого функцию, возвращающую идентификатор канала. Затем процесс может передавать данные в канал или принимать их из канала, вызывая функции, напоминающие функции записи и чтения для стандартных потоков ввода/вывода DOS. Разумеется, в процедуре передачи данных через канал должны участвовать два процесса (рис. 1.6).
Рис. 1.6. Передача данных через канал возможна между двумя различными процессами Отметим специально, что IBM OS/2 позволяет создать каналы между процессами, запущенными на различных рабочих станциях локальной сети (если установлена сеть с серверами IBM LAN Server). Таким образом, средства передачи данных по локальной сети встроены непосредственно в ядро IBM OS/2, что очень удобно для программиста. ОчередиПомимо каналов операционная система IBM OS/2 имеет другое, более сложное средство передачи данных между процессами - очереди (queue ). Очереди позволяют организовать передачу данных от нескольких "передающих" процессов к одному "принимающему". Они также часто используются для передачи данных между различными задачами внутри одного процесса. Через очередь можно передавать элементы данных размером 32 бит, причем формат этих элементов полностью определяется процессом или задачей, создавшими очередь. Схема работы очереди отличается от схемы работы канала. Процесс или задача, создавшая очередь, называется серверным процессом для очереди. Серверный процесс является владельцем очереди и может извлекать или читать (без извлечения) из нее информацию в любом порядке. Напомним, что канал можно использовать только для последовательной передачи данных. Остальные процессы, использующие очередь, называются клиентскими процессами. Они могут только записывать данные в очередь, но не читать их оттуда. Таким образом, очередь может служить для передачи данных только в одном направлении - от клиентских процессов к серверному процессу (рис. 1.7).
Рис. 1.7. При использовании очереди данные передаются в одном направлении - от клиентских процессов к серверному процессу Для синхронизации передачи данных для очереди можно назначить один семафор. Система управления памятьюСистема управления памятью IBM OS/2 Warp представляет собой сложный и совершенный механизм, с помощью которого процессы и задачи могут получать в свое распоряжение сотни Мбайт виртуальной памяти. Для того чтобы лучше разобраться в том, как выполняется адресация памяти в IBM OS/2 Warp, необходимо совершить краткий экскурс в системы управления памяти DOS и Microsoft Windows. Нужно также изучить особенности адресации памяти в защищенном режиме процессоров i386 и процессоров более старших моделей. Вы найдете подробное описание защищенного режима работы процессоров в 6 томе "Библиотеки системного программиста", который так и называется - "Защищенный режим работы процессоров Intel 80286/80386/80486". Здесь же из-за недостатка места мы рассмотрим только самые основные моменты. Управление памятью в DOSКак известно, система DOS изначально была рассчитана на реальный режим работы процессоров i8086 и i8088. Именно эти процессоры были использованы в первом компьютере IBM PC. В реальном режиме работы программы адресовались непосредственно к физической памяти, используя двухкомпонентный адрес, состоящий из сегмента и смещения. Как сегмент , так и смещение имели разрядность 16 бит. Для вычисления физического адреса использовалась простая схема: сегментная компонента сдвигалась влево на 4 бита с заполнением младших бит нулями, а затем к 20-разрядному результату добавлялась 16-разрядное смещение (рис. 1.8).
Рис. 1.8. Адресация памяти в реальном режиме Схема адресации памяти реального режима имеет много недостатков. Прежде всего, любая программа могла обратиться для чтения или записи в любую область оперативной памяти. Например, она могла разрушить таблицу векторов прерываний или операционную систему. Размер сегмента памяти не превышал 64 Кбайт, что создавало дополнительные трудности при адресации объектов данных большого размера. Для облегчения программирования предлагалось использовать различные модели памяти, а также ближние и дальние указатели, ближние и дальние функции. Программа обращалась к DOS для выделения блока памяти заданного размера, однако ничто не мешало ей выполнить запись за пределами выделенного блока памяти. Поэтому система управления памятью DOS существовала лишь номинально, фактически программы должны были сами внимательно следить за использованием памяти. Управление памятью в первых версиях IBM OS/2 и в стандартном режиме Microsoft WindowsС появлением процессора i80286, способного работать не только в реальном, но и в защищенном режиме, появилась возможность создания более совершенной системы управления памятью. Самое главное достижение защищенного режима работы процессора заключается в том, что программы не оперировали непосредственно с физическими адресами памяти, а использовали для адресации так называемые таблицы глобальных и локальных дескрипторов. Эти таблицы готовились операционной системой и программы не могли их изменить самостоятельно. Кроме того, был предусмотрен механизм защиты, с помощью которого операционная система может предотвратить доступ обычных программ к системной памяти и памяти других программ, а также аппаратная реализация мультизадачности (переключение задач). Появилось понятие "логический адрес ". Когда программа адресуется к памяти в защищенном режиме, она не указывает сегмент и смещение, вместо этого она пользуется логическим адресом. Логический адрес состоит из двух компонент - селектора и смещения. Селектор служит индексом в таблицах дескрипторов, содержащих помимо другой информации 24-разрядные базовые адреса сегментов. Дескриптор описывает сегмент памяти и содержит не только базовый адрес, но и другие характеристики, такие, например, как размер сегмента и поле доступа. Для получения 24-разрядного физического адреса базовый адрес складывается с 16-разрядным смещением (рис. 1.9).
Рис. 1.9. Адресация памяти в защищенном режиме для процессора i80286 (упрощенная схема) Эта схема адресации памяти была использована в первых версиях операционной системы IBM OS/2 и в стандартном режиме работы Microsoft Windows. Мы уже говорили, что помимо базового адреса таблица дескрипторов содержит и другую информацию. Создавая дескриптор, операционная система описывает в нем размер памяти. Если программа, адресуя блок памяти с помощью данного дескриптора, попытается выполнить чтение или запись за пределами сегмента, произойдет прерывание и работа программы будет остановлена. Таким образом, надежность операционной системы в защищенном режиме значительно повышается. Далее, для каждого сегмента памяти, описанного в таблице дескрипторов, хранится его тип. Выделяются сегменты кода, сегменты данных и системные сегменты. Программа не может ничего записать в сегмент кода, ей можно даже запретить читать сегменты кода. Сегмент кода содержит программный код и потому может только выполняться. Сегменты данных, напротив, предназначены исключительно для хранения данных. Что же касается системных сегментов, то обычная программа не имеет к ним никакого доступа. Раз уж мы заговорили о доступе, заметим, что в защищенном режиме предусмотрено три уровня доступа , называемые также кольцами защиты (рис. 1.10). Специальное поле доступа дескриптора сегмента памяти содержит номер кольца защиты, необходимый для доступа к сегменту.
Рис. 1.10. Кольца защиты Самым привилегированным является нулевое кольцо защиты, в котором располагаются сегменты операционной системы и драйверы. В первом и втором кольцах могут располагаться менее критичные системы, такие, как, например, программы обслуживания, программы, работающие с портами аппаратуры, системы управления базами данных и т. п. Обычные программы располагаются в третьем, наименее привилегированном кольце защиты. Сложная система защиты, встроенная в процессор i80286, предохраняет операционную систему от "произвола" программ пользователя. В то же время она оставляет последним возможность вызова модулей операционной системы для выполнения необходимого сервиса, такого как получение блока памяти или работа с файлами. Не имея возможности рассказать вам в этой книге подробнее о системе защиты процессора i80286, мы скажем только, что она хорошо продумана и очень надежна, так как основывается на аппаратных средствах процессора. Подробности вы можете узнать из 6 тома "Библиотеки системного программиста". Описанная выше схема адресации памяти значительно лучше той, что использовалась в DOS, однако и она не лишена недостатков. Несмотря на то что общий объем непосредственно адресуемой памяти возрос до 16 Мбайт, максимальный размер сегмента остался равным 64 Кбайт. Поэтому программисты по-прежнему вынуждены использовать различные модели памяти и модификаторы near и far . В системе может быть одна глобальная таблица дескрипторов и много локальных таблиц дескрипторов. В каждый момент времени программа может адресоваться к глобальной таблице дескрипторов и к одной из локальных таблиц дескрипторов (к какой именно - решает операционная система). Глобальная таблица дескрипторов описывает сегменты памяти, принадлежащие операционной системе. Некоторые из содержащихся в ней дескрипторов имеют уровень привилегий, равный 3, поэтому к ним можно обращаться даже из обычных программ. Для каждого процесса в IBM OS/2 создается своя локальная таблица дескрипторов . Именно поэтому адресные пространства процессов разделены физически. Таким образом, каждый процесс может адресоваться к "разрешенным" сегментам системной памяти и к своим собственным сегментам, но никак не к сегментам других процессов. Что же касается Microsoft Windows, то здесь используется одна локальная таблица дескрипторов для всех приложений. Кроме того, все приложения работают в одном, третьем, кольце защиты. Поэтому любое приложение может обратиться к сегментам памяти, созданным другими приложениями. Это снижает устойчивость системы к приложениям, содержащим ошибки. Адресация памяти в IBM OS/2 WarpОперационная система IBM OS/2 Warp способна работать только на процессоре i386 и процессорах более старших моделей. В отличие от i80286, эти процессоры могут работать в 32-разрядном режиме с использованием так называемой страничной адресации памяти. Схема страничной адресации на первый взгляд выглядит достаточно сложно. Программы оперируют с логическим адресом, состоящим из 16-разрядного селектора и 32-разрядного смещения. С помощью глобальной или локальной таблицы дескрипторов логический адрес преобразуется в 32-разрядный линейный адрес (рис. 1.11).
Рис. 1.11. Преобразование логического адреса в линейный адрес На следующем этапе преобразования 32-разрядный линейный адрес разбивается на компоненты 10-разрядного индекса в таблице страниц, 10-разрядного номера страницы и 12-разрядного смещения. Операционная система создает в памяти каталог таблиц страниц, а также одну или несколько таблиц страниц. Каждый элемент таблицы страниц описывает один блок памяти размером 4 Кбайта. Индекс в таблице страниц используется для выбора одной из таблиц страниц. Номер страницы, соответственно, является индексом в таблице страниц. В таблице страниц среди прочей информации хранится физический базовый адрес страницы. Для получения физического адреса этот базовый адрес складывается с 12-разрядным смещением (рис. 1.12).
Рис. 1.12. Преобразование линейного адреса в физический адрес Эта сложная схема адресации прозрачна для программиста, так как заполнение таблиц дескрипторов, каталога таблиц страниц и самих таблиц страниц выполняется операционной системой. Программист работает только с логическим адресом, состоящим из 16-разрядного селектора и 32-разрядного смещения. В то же время операционная система имеет большую свободу при отображении физических страниц памяти в пространство логических адресов. Незаметно для программ она может перемещать страницы в памяти или изменять физические адреса с сохранением логических адресов. Возможно отображение несмежных страниц памяти в непрерывное логическое адресное пространство, что уменьшает проблему дефрагментации оперативной памяти. Но самое главное - в процессоре i386 появилась возможность организации так называемой виртуальной памяти (процессор i80286 также мог работать с виртуальной памятью, но соответствующий механизм был не очень совершенен). При использовании виртуальной памяти часть страниц можно разместить на диске в специальном файле и загружать в оперативную память при необходимости, замещая старые или больше не нужные страницы. Для программиста виртуальная память создает иллюзию присутствия в системе оперативной памяти очень большого объема (в IBM OS/2 Warp - немного меньше 512 Мбайт). Операционная система берет на себя всю работу по выгрузке и загрузке страниц в файл виртуальной памяти, так что этот механизм полностью скрыт от программиста и удобен в использовании. Модель памяти FLATСхема преобразования адресов процессора i386 и процессоров старших моделей позволяет работать с сегментами очень большого размера - порядка 4 Гбайт. Это намного больше, чем нужно для программирования в среде IBM OS/2 Warp (хотя, кто знает - может быть скоро программисты будут работать с Гбайтными блоками оперативной памяти, ведь во времена процессора i8080 память размером 1 Мбайт считалась очень большой). В результате можно полностью отказаться от использования сегментированной модели памяти, навязанной Intel в процессоре 8086 и во всех последующих процессорах этой серии для совместимости с теперь уже музейным экспонатом - процессором 8080. Как это сделать? Очень просто - достаточно установить базовый адрес, получаемый с помощью сегментных регистров процессора, равным нулю. После этого, одним только изменением 32-разрядного смещения можно адресовать любую область памяти. Заметим, что операционная система по-прежнему может ограничивать размер сегмента, останавливая работу программы, которая по ошибке или намеренно пытается адресовать память за пределами выделенного ей сегмента. Соответствующая модель памяти называется моделью FLAT или сплошной (несегментированной) моделью памяти. Эта модель памяти чем-то напоминает модели памяти TINY и SMALL , где для адресации данных и подпрограмм было достаточно указать компоненту смещения. Отличие, однако, заключается в том, что при использовании модели памяти FLAT процессор работает в защищенном режиме и размер сегментов может значительно превосходить 64 Кбайт. Таким образом, составляя 32-разрядные программы для IBM OS/2 Warp программист может забыть про селекторы, сегментные регистры, модификаторы near и far . Содержимым сегментных регистров управляет операционная система, поэтому у программиста нет необходимости их загружать. Более того, ему категорически запрещено это делать. В состав программного интерфейса IBM OS/2 входят многочисленные функции, с помощью которых приложение может получать блоки памяти нужного размера и с нужными характеристиками. Подробное описание этих функций будет приведено в главе, посвященной системе управления памятью. Файловая системаФайловая система является тем фундаментом, на котором лежит любая современная операционная система. Именно в файлах хранятся программы и библиотеки операционной системы, программы и данные пользователя. Операционная система IBM OS/2 способна работать как с файловой системой DOS, так и со своей собственной файловой системой HPFS , которую мы кратко рассмотрим ниже. Кроме того, в IBM OS/2 есть средства монтирования других файловых систем. Вы можете установить IBM OS/2 в существующий раздел диска, созданный в стандарте DOS, либо созданный заново раздел HPFS . При этом возможно сделать так, чтобы IBM OS/2 имела доступ как к старому разделу DOS, так и к новому разделу HPFS. Подробности вы узнаете из главы, посвященной установке IBM OS/2 Warp. Недостатки файловой системы DOSОперационные системы DOS и Microsoft Windows используют файловую систему, основанную на таблице размещения файлов FAT . Эта файловая система подробно описана нами в 19 томе "Библиотеки системного программиста". Файловая система DOS обладает многими недостатками. Вы знаете, что имя файла может содержать только 8 символов плюс три символа расширения, которые обычно используются для указания типа файла. Это очень мало, так как пользователям приходится придумывать короткие имена, отражающие смысл хранящейся в файле информации. Фантазия быстро истощается и дело кончается тем, что пользователь указывает имена типа letter1.doc, letter2.doc, ..., letter234.doc или plandkld.txt. Другой недостаток схемы FAT сказывается в мультизадачных операционных системах, когда несколько программ одновременно работают с разными файлами. Таблица FAT, каталог и файл находятся в трех различных и, как правило, несмежных областях диска, поэтому для чтения файла нужно выполнить много перемещений головок. Это длительная процедура даже для одного файла, а представьте себе, что пять программ одновременно требуют доступ к десяти файлам! Файловая система HPFSДля повышения производительности IBM OS/2 была создана файловая система HPFS (High Performance File System - высокопроизводительная файловая система). Эта файловая система оптимизирована для мультизадачной среды и ускоряет одновременную работу программ с файлами, расположенными на дисках большого объема. Специальный алгоритм размещения файлов значительно уменьшает вредное влияние фрагментации файлов, уменьшающей общую производительность системы. При размещении файла для него подбирается подходящий непрерывный свободный участок диска и оставляется некоторый запас свободного пространства "на вырост". Когда файл расширяется, для него выделяются в первую очередь секторы, относящиеся к зарезервированному для этого файла участку диска. Если же размер файла увеличился значительно, для него может быть выделен еще один или несколько свободных участков. При использовании HPFS пользователь может указывать имена файлов размером до 254 символов, причем имя может состоять из заглавных и прописных букв, а также пробелов и некоторых других символов, например, символов "." (в произвольном количестве). В дополнение к таким атрибутам файлов, как "только читаемый", "скрытый", "системный" и "архивированный", IBM OS/2 хранит для каждого файла набор расширенных атрибутов. Это тип файла, комментарий и ключевые слова для поиска, пиктограмма для визуального представления файла и т. д. В распоряжении программиста имеются многочисленные функции программного интерфейса IBM OS/2, с помощью которых можно выполнять операции с файлами, в том числе и многозадачные. Например, можно запустить операцию чтения или записи фрагмента файла как отдельную задачу, которая будет выполняться автономно от запустившей ее задачи. Есть средства и для работы с расширенными атрибутами файлов, для создания, удаления и переименования файлов и каталогов, а также другие необходимые функции. Библиотеки динамической компоновкиПри компоновке программы DOS в загрузочный exe-файл добавляется программный код функций, взятых из стандартных библиотек транслятора или из дополнительных библиотек. Этот метод компоновки называется статическим. При его использовании файл программы DOS содержит в себе все, необходимое для работы,€ за исключением кода функций DOS и BIOS, вызываемого с помощью программных прерываний. В мультизадачной среде такой подход приведет к неэкономному использованию самого дефицитного ресурса - оперативной памяти, так как в нее будет загружено несколько копий одних и тех же модулей. Поясним это. Пусть, например, пользователь запустил несколько разных программ, каждая из которых вызывает стандартную функцию sprintf. Если программы подготовлены методом статической компоновки, в оперативной памяти окажется несколько экземпляров кода функции sprintf, по одному на каждую программу. Причем каждая программа будет пользоваться только своей копией функции (рис. 1.13).
Рис. 1.13. При статической компоновке в памяти может находиться одновременно несколько копий одной и той же функции В IBM OS/2, как и в других мультизадачных операционных системах, применяется динамическая компоновка, исключающая дублирование кода функций в описанной выше ситуации. Для этого группы используемых вместе функций объединяются в файлы с расширением имени .dll , которые называются библиотеками динамической компоновки, динамическими библиотеками или просто dll-библиотеками. В процессе компоновки код внешних функций, расположенных в dll -библиотеке, не включается в загрузочный exe-файл программы. Вместо этого там располагается ссылка на внешние функции, которая разрешается во время работы программы. Когда запускается первая программа, использующая функцию из dll -библиотеки, вся библиотека загружается в оперативную память. Если теперь пользователь запускает вторую копию этой же программы или другую программу, вызывающую эту же функцию, будет использован код функции, уже загруженный в память в процессе работы первой программы (рис. 1.14).
Рис. 1.14. При использовании динамической компоновки в память загружается только одна копия функции Так достигается значительная экономия памяти, поэтому библиотеки динамической компоновки очень широко используются в практике программирования для IBM OS/2. Скажем даже больше - ядро IBM OS/2 в основном состоит именно из dll -библиотек, поэтому многие функции ядра доступны программам через механизм динамической компоновки. ДрайверыПрограммы DOS часто вынуждены работать непосредственно с портами периферийных устройств, таких как видеоконтроллер или асинхронный адаптер. Это связано с тем, что DOS и BIOS не имеют в своем составе достаточно удобных и быстродействующих средств, необходимых для работы с этими устройствами. Когда программисту нужно обеспечить, например, быстрый вывод изображения на экран монитора для создания динамичной игры или разработать телекоммуникационную программу, ему приходится изучать аппаратное обеспечение компьютера, становясь в какой-то степени системным программистом. Однако на этом пути есть много подводных камней. Во-первых, очень трудно найти подробное описание портов видеоконтроллеров и другой аппаратуры, так как оно поставляется фирмами-изготовителями по отдельному соглашению и далеко не всем желающим. В результате программист не может воспользоваться возможностями аппаратуры в полной мере, ограничиваясь стандартами вроде VGA или VESA SVGA . Во-вторых, разнообразие аппаратуры очень велико. Сейчас разными фирмами выпускаются десятки и сотни несовместимых друг с другом видеоконтроллеров, принтеров, контроллеров дисков и т. д. В-третьих, аппаратура постоянно совершенствуется. Новые периферийные устройства не всегда совместимы со старыми устройствами, даже изготовленные одной и той же фирмой. Поэтому старые программы либо не удается запустить на новом компьютере, либо они работают, но не так как нужно. В составе IBM OS/2 поставляется набор драйверов для всех стандартных устройств компьютера, обладающих прекрасными скоростными характеристиками, что полностью исключает необходимость работы с аппаратурой на уровне портов. Что же касается видеоадаптеров, принтеров, SCSI -контроллеров, звуковых адаптеров и устройств чтения компакт-дисков, то IBM OS/2 способна работать со многими из них. Подробный список вы найдете в главе, посвященной установке IBM OS/2. Для тех устройств, которые IBM "забыла", вы можете получить драйверы у производителя аппаратуры. Однако будьте осторожны, приобретая устройства, которые не поддерживаются IBM OS/2. Следует обязательно убедиться, что вместе с ними поставляется драйвер именно для той версии операционной системы, которую вы собираетесь использовать. |