developing.ru - клуб программистов Здесь может быть и ваша реклама.
developing.ru >технология COM >
Михаил Безверхов
aspid@developing.ru

А процесс - это химия...

Углубим наши знания относительно тех концепций, что излагались в прошлой статье. Поскольку движение от частного к общему даётся значительно легче, чем наоборот, сегодня мы рассмотрим в бОльших деталях, как реализуется "изолированное адресное пространство". В следующих статьях - "поток" и "процесс".

Какое отношение это имеет к COM? Самое непосредственное! COM – означает приложение, "разложенное" на несколько частей. И эти части могут выполняться в разных местах создавая иллюзию, что они выполняются в месте одном. Но это – не более, чем иллюзия. И когда ей поддаётся программист, когда начинает считать, что приёмы программирования применимые исключительно в монолитном приложении применимы и здесь – плохо. Ставший уже классическим пример описывается вопросом "... я сделал COM-сервер. Он работал. Но, когда я оформил его в виде EXE – при попытке передать строку я получаю нарушение защиты памяти. Почему?" Можно, конечно, объяснить, что строки должны выделяться в "разделяемой памяти", а ... что это такое "разделяемая память"? Поэтому я считаю, что есть смысл узнать об операционной системе и о механизмах нижнего уровня побольше – зная их устройство и зная концепции COM можно просто избежать ряда "граблей" ещё на этапе обдумывания конструкции.

Итак, начнем, как у нас принято – с философии. Мы, программисты, понимаем память, как некое устройство, состоящее из массива ячеек (именуемых, обычно, байтами). Ячейки последовательно перенумерованы и номер ячейки называется "адрес". Наше обращение с памятью простое - мы можем "читать" или "записывать" байт с указанным адресом. В промежутках между операциями записи память хранит то значение, которое в неё было записано последним. То, что операции с памятью возможны и более длинными блоками не изменяет концептуальной модели памяти - "строка байтов".

Естественно, что строка эта не бесконечна - у неё есть начало и есть конец. С началом обычно всё понятно - отрицательными адреса быть не могут, а вот что считать "концом"? Вопрос этот только кажется идиотским, потому, что можно рассматривать не один, а два ограничителя. Первый, естественно, размер физического банка памяти - 0 - 1K ...1M ... 128M... причём нас, программистов, совершенно не интересует как это всё электротехнически реализовано. Я, помнится, был в своё время очень удивлён узнав, что разные биты одного байта хранятся в разных микросхемах :) Но есть и второй ограничитель - разрядность адреса. Если у нас разрядность адреса 8 бит, то мы может адресовать 256 байтов. Пусть у нас физически есть хоть 1Mb - больше мы адресовать не сможем. При разрядности адреса в 16 бит нам будет доступна память в 64K - и не более того. Чтобы адресовать в этих условиях больше нужно идти на всякие ухищрения. Например, в процессорах 8086 - 80286 адресация двухкомпонентная - есть "сегмент", который хранит старшие биты адреса, есть "смещение в сегменте", которое представляет собой младшие биты адреса. Эти значения "склеиваются" и получается полный физический адрес, который процессор выставляет на шину. На самом деле они складываются со сдвигом (который есть 4 бита) и получается 20-тибитный адрес, который позволяет адресовать... ровно 1Mb. Если учесть, что одно и то же число можно представить весьма немалым количеством пар слагаемых, то понятно, что программирование в такой системе начинает приобретать черты кошмара - банальная проверка равенства адреса требует не простого сравнения, а вычисления адреса настоящего. Именно поэтому программисты не любят всякие "сегментированные адресные пространства", а любят адресные пространства "плоские" - те, в которых адрес всякого байта есть одно число в программе.

Но обратим своё внимание вот на что. Было время, когда 4K считалось "много", а вся машина укомплектовывалась "приличным" объёмом памяти в 64K. И разрядность в 16 бит - считалась очень хорошей! Словом, имело место быть некоторое примерное соответствие двух ограничителей - разрядности адреса и ёмкости физического устройства памяти (здесь, конечно, речь идёт не о физической возможности построить устройство памяти заданной ёмкости, а о том, будет ли его цена приемлемой для покупателя). В процессоре x86 разрядность адреса (20) оказалась больше, чем разрядность самого процессора (16) и это потребовало специальных ухищрений в программировании, но примерное соответствие двух ограничителей опять имело место быть - там, где машину можно было укомплектовать 512K можно было укомплектовать и 1Mb памяти. А вот начиная с 80386 разрядность адреса стала 32 бита, а ёмкость устройства физической памяти возросла только в два-четыре раза! Иными словами, адрес позволял адресовать 232 = аж 4Gb, а машина комплектоваласть только 2-4-8Mb памяти... И это несоответствие - очень резало глаз. Программа могла адресовать 4Gb, но физически получала только 4Mb. Если учесть, что и "скорострельность" процессора возросла, т.е. он в приемлемое для пользователя время мог обрабатывать уже очень большие объёмы данных эти 0.1% доступной памяти при 100% возможной действительно стали узким местом.

Поэтому на повестку дня был поставлен совершенно фантастический вопрос - как, ограничиваясь весьма малой реальной памятью (определяющей цену машины), сделать так, чтобы программа могла адресовать весь диапазон адресов так, как будто бы она действительно эту память имеет (определяющей возможность обрабатывать большие массивы данных)? Техническое решение этого было уже известно, оно пришло ещё из 60х - 70х годов, но ранее оно просто не требовалось. А при таком несоответствии одного другому - стало просто чрезвычайно актуально.

Это решение называется "виртуальная память", оно реализуется программно-аппаратно и весьма примечательно тем, что на уровне прикладного программиста и программы пользователя сохраняет для программиста парадигму "плоской строки байт", которая ограничена только разрядностью адреса машины. Объём же действительно имеющейся в наличии физической памяти неважен. Нет, конечно, не совершенно неважен - он влияет на совокупное быстродействие, но концептуально, для программы, значения не имеет. Поэтому "реальная" или "виртуальная" в системе память - программист может не беспокоиться. Он может писать программы так, как и всегда писал. Но "виртуальная память" предоставляет в распоряжение программиста дополнительные степени свободы, поэтому в системе с виртуальной памятью работать всё-таки значительно удобнее, чем в системе с памятью реальной.

Как это сделано? Принципиально весьма несложно. Довольно подробное описание, которое, к тому же, будет продолжаться как самостоятельная тема, находится здесь. Желающие приглашаются ознакомиться – автор тот же.

Но, поскольку тема нашей серии - COM, а не организация механизмов ядра операционной системы здесь мы и остановимся. Желающие поподробнее узнать функционирование механизма виртуальной памяти отсылаются к книге (например!) Джеффри Рихтера "Windows для профессионалов" и к MSDN. А в следующей статье мы так же "подробно-обзорно" рассмотрим "потоки"...

предыдущий выпускархив и оглавлениеследующий выпуск
Авторские права © 2001 - 2004, Михаил Безверхов
Публикация требует разрешения автора

разделы сайта

форум

технология COM

оптимизация сайтов


© 2000-2004 Клуб программистов developing.ru