Операционная система UNIX. Руководство программиста




Подготовка исходного текста для разделяемой библиотеки - часть 2


Из архивной библиотеки редактор внешних связей извлекает отдельные элементы, поэтому программисты обычно помещают функцию и соответствующие ей данные в один и тот же исходный файл. Это хорошо только при условии, что адреса данных определяются в процессе редактирования связей, однако для разделяемых библиотек имеется ряд ограничений. Если внешние (экспортируемые) переменные разбросаны по различным модулям библиотеки, они перемешиваются с невидимыми пользователю данными. Изменение этих невидимых извне данных, например цепочки символов "hello" в следующем примере, приводит к смещению остальных данных, в том числе и экспортируемых.

Рассмотрим два варианта программы:

int head=0; int head=0; func() func() { { . . . . . . p="hello"; p="hello, world"; . . . . . . } } int tail=0; int tail=0;

Пусть относительный виртуальный адрес переменной head будет нулевым для обоих примеров. Текстовые константы тоже будут иметь одинаковые адреса, но их длины различны. Старый адрес tail будет равен 12, а новый - 20, поэтому, если предполагается, что переменная tail будет доступна извне библиотеки, две приведенные версии программы будут несовместимы.

Добавление новых экспортируемых переменных в разделяемую библиотеку может изменить адреса статических имен, но это не влияет на совместимость. Выполняемый файл не может прямо ссылаться на статические имена, поэтому он не зависит от их адресов. В связи с этим, следует собрать вместе все экспортируемые данные и разместить их выше (с меньшими адресами) статических (невидимых) данных. Для этого в списке объектных файлов файла спецификаций указывайте первыми файлы с глобальными данными:

#objects data1.o . . . lastdata.o text1.o text2.o . . .

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

Пользователи разделяемой библиотеки, независимо от организации исходных файлов библиотеки, получают всю ее область данных во время выполнения. Поэтому Вы можете без опасений хранить описания всех экспортируемых переменных в одном исходном файле. Разумеется, их можно хранить и в нескольких файлах.




Содержание  Назад  Вперед