IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  AIX и UNIX  >

Перенос приложений Tru64 на AIX

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: простой

Гарри Хук, старший технический консультант, IBM
Вандана Кумар, ISV Global Solutions Enablement Strategy, IBM

12.08.2009

Вам нужно перенести приложение с платформы Compaq Tru64 на платформу IBM AIX? В большинстве случаев для переноса приложения потребуется только его перекомпиляция, но встречаются и исключения. Данная статья рассматривает различные сценарии миграции приложений и фокусируется на примерах, в которых для облегчения переноса приложения с Tru64 на AIX нужно вносить изменения в его исходный код или в способ его сборки. Последняя версия AIX (AIX 5L 5.1) может работать на процессорах PowerPC и Itanium. В этой статье рассматривается перенос приложений Tru64 на архитектуру AIX PowerPC.

Полезные термины и определения

  • ILP32 - исходный код 32-битного приложения. В этой модели размер типов int, long и pointer (указатель) для C и C++ составляет 32 бита.
  • LP64 - исходный код 64-битного приложения. В этой модели размер типа int для C и C++ составляет 32 бита, тогда как размер long и pointer составляет 64 бита.
  • AIX 5L - 5-я версия операционной системы AIX для платформ PowerPC и Itanium.
  • Little Endian (LE) - в слове данных байты записываются в порядке от младшего к старшему.
  • Big Endian (BE) - в слове данных байты записываются в порядке от старшего к младшему.
  • Endian-Sensitive Application - исходный код приложения, зависящего от порядка расположения байтов.
  • Endian-Neutral Application - исходный код приложения, не зависящего от порядка байтов.


В начало


Обзор

Большинство приложений написано на высокоуровневом языке. Так как для переноса приложений, написанных на ассемблере или макроассемблере, потребуется их целиком переделывать, мы рассмотрим проблемы при переносе, связанные с языками C и C++. Подобные проблемы возникают и с другими языками.

Большинство хорошо написанных на C и C++ программ будут компилироваться и работать на AIX без каких-либо изменений в исходном коде. Под "хорошо написанными" понимается использование полезных методик программирования:

  • совместимость со стандартом ANSI/ISO C;
  • возможность переноса приложения на другую платформу учитывалась на различных этапах жизненного цикла ПО: проектирования, реализации, обслуживания;
  • повсеместное использование прототипов функций.

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



В начало


Краткое описание AIX

AIX - это операционная система UNIX от IBM, предназначенная для выполнения критически важных бизнес-процессов. На данный момент доступны две версии AIX - 4.3.3 и 5.1.

Мощные возможности и функции AIX хорошо себя показали за годы использования на самом широком диапазоне серверов, от сравнительно маленьких однопроцессорных систем до гигантских суперкомпьютеров Scalable POWERParallel (SP) IBM. AIX 5L 5.1 обладает следующими возможностями:

  • поддержка 32-битных и 64-битных ядер;
  • поддержка 32- и 64-битных прикладных программных интерфейсов (API);
  • близость к Linux, которая позволяет пользователям выполнить плавный перенос технологий между AIX и Linux;
  • для балансировки наиболее сложных рабочих нагрузок применяется Workload Manager;
  • упрощенное управление системой - утилита SMIT (System Management Interface Tool), включая версию с Web-интерфейсом.

Tru64 содержит 64-битное ядро, основанное на компонентах из Berkeley Software Distribution (BSD) 4.3 и 4.4, UNIX System V и других источников.



В начало


Основные различия между AIX И Tru64

Определение числовых значений

Все определения числовых значений могут быть найдены в /usr/include/sys/limits.h и /usr/include/float.h на AIX, а также в /usr/include/limits.h на /usr/include/alpha/machlimits.h на Tru64.

Из-за различий в архитектурах у этих двух ОС есть некоторые различия в максимальных и минимальных значениях стандартных типов.

Типы данных

Тип double в AIX (32- и 64-битной версии) имеет размер 8 байтов, но выровнен он по 4-байтной границе. См. таблицы ниже:


таблица 1.0

таблица  1.1

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

В таблице 1.2 приведены четыре опции выравнивания, поддерживаемые компилятором.


таблица  1.2

Опции компилятора

AIX предоставляет полную поддержку ANSI-спецификаций языков С и С++. Последняя версия компилятора AIX, VisualAge for C and C++ V5.0 (VAC 5.0), поддерживает самые свежие нововведения этих языков.

Исполняемые файлы компилятора установлены в /usr/bin/vac для C и в /usr/bin/vacpp для C++. По умолчанию справочная документация находится в /usr/vachtml/en-US/doc/index.htm для C и в /usr/vacpp/bin/vacpphelp для C++. В пятую версию компилятора включены несколько стандартных конфигураций (файл /etc/vac.cfg), которые используются в зависимости от вызываемого драйвера программы. Например, чтобы скомпилировать программу на ANSI C с UNIX98-потоками, используется команда use /usr/vac/bin/xlc_r. Чтобы скомпилировать программу на ANSI C с использованием библиотеки потоков POSIX Draft 7, следует выполнить команду /usr/vac/bin/xlc_r7. Для приложений с потоками на C++ используется команда /usr/vacpp/bin/xlC_r.

По умолчанию компилятор создает 32-битный объектный код. Чтобы скомпилировать приложение в 64-битном режиме под AIX, следует использовать опцию -q64. Другим способом получения 64-битного объектного кода является установка переменной среды OBJECT_MODE=64. Опция -qwarn64 предупредит о возможных проблемах с переносом приложения, связанных с его 64-битностью.

Следует отметить, что любая сторонняя библиотека, скомпонованная с 64-битным приложением, должна также быть 64-битным приложением. Чтобы определить разрядность (object mode) любого модуля или библиотеки в AIX, необходимо выполнить команду:

> dump -X32 -ov <file name>

file_name - это имя любого объектного модуля, например libxyz.a. В выведенных данных нужно выполнить поиск строки XCOFF. Однако команда, приведенная выше, предназначена только для 32-битных модулей. Для 64-битных модулей следует использовать:

> dump -X64 -ov <file name>

Библиотеки и архивы

В AIX любой архив может содержать объекты различных типов. Например, libc.a содержит 32- и 64-битные файлы с расширением .o, 32-битные общие библиотеки и 64-битные общие библиотеки. 32- и 64-битные приложения могут динамически или статически компоноваться с этим архивом (libc.a). Tru64 также предоставляет библиотеки архивации в дополнение к общим библиотекам. Однако загрузчик и компоновщик на AIX функционируют несколько иначе, чем на Tru64.

В AIX разрешение символов (symbol resolution) выполняется на этапе компоновки. Если символ определен в общем объекте (или модуле), указанном в командной строке, компоновщик запишет имя символа и описание модуля в загрузочный раздел программы. Когда программа будет выполняться, импортируемые символы будут найдены в описанном модуле согласно информации, записанной на этапе компоновки.

Невозможность сопоставить символ с заданной библиотекой на платформах, отличных от AIX, показывает важность правильного порядка задания библиотек. Например, если речь идет о rpc и необходимо воспользоваться функциональностью потоков, то библиотеки следует указывать в следующем порядке: libnsl, затем libc. Если нужно воспользоваться сокетами, то следует после libc указать libnsl. Например:

  1. Модуль А содержит определение функции Х.
  2. Библиотека foo также содержит определение другой функции Х.
  3. У библиотеки foo имеется функция Y, которая вызывает функцию X.

Если приложение, использующее оба этих модуля, скомпоновано при помощи команды, в которой A указан перед foo, тогда ссылки на символы будут обработаны так:

  • в AIX функция Y получит X из библиотеки foo;
  • в Tru64 функция Y получит X, представленный в модуле A.

Если приложение скомпоновано командой, в которой foo указано перед A, то поведение этого приложения на AIX останется таким же, а на Tru64 функция Y вызовет экземпляр X из foo.

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

Более подробная информация, полное описание механизмов компоновки и загрузки AIX, различные опции компоновщика, примеры и FAQ доступны по этой ссылке.

Проблемы при смешивании языков

Для Tru64-приложений, использующих несколько языков программирования (например, такие, которые вызывают Fortran-процедуры из С-функций), требуется инициализация среды исполнения Fortran командой for_rtl_init routine. Подобный пример приведен ниже:

/* выполняется инициализация fortran... */
        printf ("Initializing DEC F77 RTL Environment\n");
        for_rtl_init_ (&argc, argv);

В AIX, даже в приложениях, использующих различные языки программирования, для инициализации библиотек не требуется специальных вызовов. Все системные библиотеки инициализируются самостоятельно. Это также относится к приложениям, написанным на C++. До тех пор, пока соблюдаются стандартные соглашения о вызове, вызов Fortran-функций из C, или наоборот, не является проблемой (т.е. вызов по ссылке vs. - вызов по значению.)

Некоторые написанные на FORTRAN приложения Tru64 могут использовать VMS-возможности типа shcom_connect(). Эта функция позволяет приложениям помещать общий блок данных в область памяти, доступную для чтения-записи, которая доступна нескольким процессам (т.е. общим образам). В AIX (или других UNIX-системах) для реализации этой возможности используется общая память. Алгоритм использования общей памяти в данном случае таков: сборка приложения (общие блоки располагаются в областях общей памяти), создание и присоединение сегментов общей памяти, заполнение этих сегментов данными.

Проблемы с порядком байтов

Архитектура PowerPC позволяет использовать оба порядка байтов. Тем не менее, AIX на PowerPC использует порядок байтов "о старшего к младшему". Архитектура Alpha имеет порядок байтов "от младшего к старшему". Порядок байтов указывает на то, как хранится (или адресуется в памяти) элемент данных и отдельные байты. Для порядка "от старшего к младшему" (big-endian, далее - BE), младший адрес ассоциируется с наиболее значительным байтом (крайним левым) многобайтного значения. В случае порядка "от младшего к старшему" у наименьшего адреса наименьшая значимость (т.е. наименьшая значимость крайне правого байта) байта многобайтного значения. В общем, нулевой бит ассоциирован со старшим битом в (MSB) для BE и является младшим битом в LE.

Ниже приведены 4-байтные слова с различным порядком байтов (LE и BE); они показывают, что сами данные в обоих случаях остаются одинаковыми, несмотря на порядок байтов, составляющих их (рисунок 1.0); в то же время адреса байтов данных различны. Просто байты записываются в различных направлениях, все остальные детали одинаковы.


рисунок 1.0

Рисунок 1.1 показывает структуру сложного 64-битного значения типа double, состоящего из нескольких элементов данных. Переменные a, b и c расположены по одним и тем же адресам: 00, 04 и 06 в обоих случаях. Элементы данных и отдельные байты, составляющие их, хранятся в порядке "слева направо" для BE. Для LE, с другой стороны, элементы данных хранятся в порядке "справа налево"; в то время как отдельные байты элемента данных имеют порядок "слева направо". Данное обстоятельство может стать причиной неудобных ситуаций, особенно при чтении дампов памяти на машине с порядком байтов "от младшего к старшему".


рисунок 1.1

Порядок байтов не является проблемой, если программа, которая записывает в память слово данных, потом прочитает из этой области памяти записанные ранее данные за одно обращение (при условии, что обращение к этой области данных будет происходить последовательно). Если программа пытается прочитать то же самое значение, считывая за раз по одному байту, она может получить различные результаты в зависимости от того, какой порядок данных - BE или LE.

Сегменты памяти

В AIX аппаратное обеспечение для доступа к данным предоставляет последовательный диапазон адресов виртуальной памяти, начиная с 0x00000000000000000000 до 0xFFFFFFFFFFFFFFFFFFFF. Максимальный размер памяти, поддерживаемый адресным пространством, - более 1 триллиона терабайтов. Процедуры доступа к памяти генерируют 64-битные адреса: 36 битов для выбора сегмента и 28 битов для определения смещения внутри сегмента. Эта схема адресации позволяет получить доступ более чем к 64 миллионам сегментов, по 256 Мбайт в каждом. Каждый сегментный регистр содержит 52-битный идентификатор сегмента, который является префиксом для 28-битного смещения; вместе идентификатор сегмента и величина смещения составляют адрес виртуальной памяти. Получившийся таким образом 80-битный виртуальный адрес указывает на единое для всей системы пространство виртуальной памяти. Адресное пространство процесса имеет разрядность 64 бита, т.е. программы используют 64-битные указатели. Однако каждый процесс или обработчик прерывания может обращаться только к единому для всей системы пространству виртуальной памяти; идентификаторы сегментов, из которых состоит эта виртуальная память, находятся в регистре сегментов.

64-битная прикладная программа, выполняющаяся на системе, имеет адресное пространство, поделенное на сегменты.


таблица 1.3

В AIX 64-битные приложения всегда загружаются по адресу 0x0000000100000000. Заметим, что ядро отображается в младший сегмент памяти (low memory), начинающийся с адреса 0x0. Тем не менее, хотя 32-битные указатели не могут использоваться для доступа к любой части 64-битного адресного пространства приложения, при помощи 32-битных указателей можно прочитать данные с сегмента ядра (в нижней области памяти, с младшими адресами).

Более исчерпывающую информацию о модели памяти в AIX можно найти в онлайновой документации.

В строку поиска необходимо ввести фразы: "Program Address Space Overview" (обзор адресного пространства программы) или "Understanding Memory Mapping" (разбор отображения памяти).

Опции на этапе выполнения

Чтобы AIX 4.3.3 могла выполнять 64-битные приложения, в ней должен быть установлен набор файлов bos.64bit. (Чтобы узнать, установлен ли уже этот пакет, воспользуйтесь командой lslpp -L|grep bos.64bit. Если он не установлен, то его можно взять с установочного CD AIX.)

AIX 5L можно загрузить с 32- или 64-битным ядром. Начиная с AIX 5L, все 64-битные и 32-битные приложения могут выполняться на ядрах обоих разрядностей. Однако, если наиболее важные приложения, выполняющиеся на системе, являются 64-битными, рекомендуется загружать сервер с 64-битным ядром, чтобы программа могла полностью воспользоваться аппаратными возможностями. 64-битное ядро запаковано вместе с набором файлов bos.mp64. Если выбрана опция "Enable 64-bit Kernel and JFS2" (выбрать 64-битное ядро и JFS2) из подменю "Advanced Options" (расширенные опции) меню "Installation" (установка) и "Settings" (настройки), данный набор файлов устанавливается автоматически. Кроме того, в случае выбора этих опций загрузка 64-битного ядра будет производиться по умолчанию.

При нормальной установке 32-битное ядро становится ядром по умолчанию. При помощи следующих команд можно заставить загружаться систему с использованием 64-битного ядра:

> ln -sf /usr/lib/boot/unix_xx  /unix
> ln -sf /usr/lib/boot/unix_xx  /usr/lib/boot/unix
> bosboot -ad /dev/ipldevice
> shutdown -r

где unix_xx:
		unix_up	- 32-битное uni ядро
		unix_mp	- 32-битное mp ядро
		unix_64	- 64-битное mp ядро

Настройка производительности

Одно из наиболее значительных различий в производительности проистекает из адресуемости байтов в AIX, которая предоставляет возможность загрузки отдельных байтов, полуслов, слов, двойных слов (double words - 8 байт) на 64-битных компьютерах через атомарные операции. Это позволяет компилятору избегать необходимости генерировать дополнительные инструкции для управления этими маленькими элементами данных, что приводит к увеличению пропускной способности памяти. (Следует помнить о различии между двумя рассматриваемыми платформами: размер слова данных в AIX равняется 32-битам, т.е. слово на AIX может быть представлено как два слова данных в Tru64.)

Значительное различие между AIX и Tru64 (как и любой другой UNIX-системой) заключается в том, что конечный пользователь или системный администратор не модифицирует конфигурационные файлы ядра и, следовательно, ему не нужно перекомпилировать ядро. Все параметры AIX, которые можно настроить при помощи команды smit (smitty chgsys), команды >vmtune или команды >schedtune, можно найти в файле >>/usr/samples/kernel.

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

pthreads

Существует несколько небольших различий между библиотеками pthreads в Tru64 и AIX. AIX предоставляет поддержку для создания приложений, написанных в соответствии со спецификациями Draft 10 и Draft 7 POSIX-потоков 1003.1c threads, а также предоставляет некоторые специфические расширения. Рекомендуется в документации AIX прочесть описание прикладных программных интерфейсов (API).

Обслуживание и поддержка

Исправления и обновления AIX могут быть загружены с этого сайта.



В начало


Проблемы при миграции

Если на многобайтные элементы данных не ссылаться по отдельным байтам (или их совокупностям), то программный модуль, скомпилированный независимо от порядка байтов, в большинстве случаев сам определит порядок байтов. С другой стороны, при использовании структуры данных типа union, при преобразовании типов элементов данных, при выполнении операций с битовыми полями может происходить обращение к отдельным байтам сложного типа данных с использованием обратного порядка байтов. Это может вызвать некоторые проблемы при портировании программного кода между LE- и BE-компьютерами. Другим источником зависимостей от порядка байтов является совместное использование данных на различных платформах. Обычно в этом случае данные конвертируются в каноническую форму, что позволяет избежать зависимости от порядка байтов. Также проблемы с порядком байтов возникают при взаимодействии с внешними устройствами (но эти проблемы обычно решаются программными и/или аппаратными решениями).

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

Зависимости от порядка байтов

Несоответствие типов данных

Несоответствие типов данных является главным источником зависимости от порядка байтов. Чтобы избежать проблем с зависимостью от порядка байтов, на этапе выполнения данные обрабатываться согласно своему типу. Случаи, для которых необходимо вмешательство, можно обнаружить путем изучения программного кода или с помощью lint. lint может указать на возможные преобразования типов, которые скрывают в себе проблемы, связанные с порядком байтов.

Например, 4-байтное целое значение (integer) должно быть обработано процессором как неделимый элемент данных типа integer. Отдельные биты и байты типа просматриваются в противоположных направлениях в LE и BE. Как показано в следующих примерах, обращаясь к типу integer как к меньшему типу данных, можно получить различные результаты в LE- и BE-процессорах.

int         a = 0x11121314;
char        b,  *ptr;
...
ptr = (char *) &a;    // указатель ptr указывает на a
b = ptr[1]            // b равно 0x13 в LE и 0x12 в BE
...

Чтобы порядок байтов, используемый в программном коде выше, не влиял на портирование, код следует изменить.

#define         BIG_ENDIAN		0
#define 	LITTLE_ENDIAN	1
int		a = 0x11121314;
char 		b, *ptr;
...
char endian() {
           short	t = '0x0001;
		   //возвращает 00 для BE и 01 для LE
           return *((char *) &t);	                  
}
...
// указатель ptr указывает на a
ptr = (char *) &a;			                  
// b равно 0x12 в BE и LE
if (endian() == BIG_ENDIAN) b =  ptr[1]; else b=prt[2];   
...

В этом случае для обнаружения порядка байтов на этапе выполнения используется процедура endian(). Это необходимо для компьютера, который динамически поддерживает оба порядка хранения данных. Однако за возможность проводить проверку на этапе выполнения приходится платить производительностью. При портировании на AIX желательно, чтобы использовалась условная компиляция для предопределенной модели данных (LE или BE). Это позволит избежать проблем с производительностью на этапе выполнения.

Лучшим решением для изложенной выше проблемы будет использование решения, не зависящего от порядка байтов.

/*
 * макрос для получения 16-23 битов (на основе значимости
 * позиций битов) из integer значения выполняется сдвижкой
 * битов вниз до позиции нулевого бита и таким образом отрезая
 * наиболее значительные 24 бита.
 */
	#define INTB16TO23(a)  ((a >> 16) & 0xff)
	...
	b =  INTB16TO23(a);	// b равно 0x12 в BE и LE
	...

В этом примере, так как коду нужно хранить биты 16-23 в переменной b, использование операции сдвига позволяет процессору управлять многобайтными данными как одним целым и выполнять над ними подходящие операции.

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

short	a[2];
	int 	b;
	...
	a[0] = 0x1112;
	...
	a[1] = 0x1314;
	...
	b =  *((int*) &a[0]);	// b равно 0x11121314 в BE и  0x13141112 в LE
	...

Несовпадение типов данных может также возникнуть при использовании структуры данных типа union. union позволяет переменным, содержащим элементы данных разных типов, хранить свои данные в общей области памяти. Но если данные записываются в общую память под одним порядком байтов, а читаются под другим, то LE и BE могут прочитать различные данные.

        union short_or_int {
	        short 	a[2];
	        int	b;
	};
	short c;
	...
	short_or_int.b = 0x11121314;
	c = short_or_int.a[0];		// c равно 0x1112 в BE и 0x1314 в LE
	...

Итак, проблема заключается в том, что LE и BE обращаются к данным типа short data short_or_int.a[] в объединении (union) в противоположных порядках, а вот целочисленное значение short_or_int.b остается неизменным в обеих моделях хранения данных.

Перекрывающиеся данные (с битовыми полями)

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

Например, обычно дескриптор (в драйверах устройств) использует одно слово для флагов и указателя. Данные в дескрипторе хранятся так: в старшем байте хранятся флаги, а в остальных младших байтах хранятся 16- или 24-битные указатели (адреса).

Кроме того, для эффективного использования памяти можно хранить закодированные данные в типе int. Следующий пример кода показывает 4-байтное слово, используемое для кодирования персональных данных.

       struct personal_data{
		unsigned age:7;	//возраст от 0 до 128
		unsigned height:7;	//рост от 0 до 128
		unsigned gender:1;	//пол (муж/жен)
		unsigned pad:17;	//выравнивание по границе слова
	};

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

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

Чтобы при портировании программы с BE-компьютера на LE-компьютер обратиться к зашифрованным данным из этого примера, необходимо преобразовать структуру данных.

       struct personal_data{
		unsigned pad:17; 	//выравнивание по границе слова
		unsigned gender:1;	//пол (муж/жен)
		unsigned height:7;	//рост от 0 до 128
		unsigned age:7;	//возраст от 0 до 128
	};

Чтобы после перестановки позиций битовых полей в структуре получить значение, которое может быть использовано на BE-системах, придется переставлять все байты целочисленного значения. Из-за способа, при помощи которого компиляторы создают структуру данных, понадобится выполнять обнуление. Компилятор gcc на LE-платформах может самостоятельно выполнять преобразование из LSb в MSb. Компилятор gcc на BE платформе и компилятор AIX могут преобразовать MSb в LSb. Таким образом, в этом примере мы полностью переписываем наоборот все поля так, чтобы LE-компилятор, выполняя преобразование из LSb в MSb, создавал структуру данных, которая преобразовывалась бы из MSb в LSb как компилятор BE.

При более пристальном анализе этого примера программного кода можно заметить, что причиной изменения кода при портировании является необходимость совместного использования данных между LE-компьютерами и BE-компьютерами. Хотя на LE- и BE-компьютерах хранение данных и обращение к ним происходит в противоположных порядках, компьютеры не должны заботиться о том, чтобы обращение к каждому битовому полю происходило должным образом. Однако существует исключение: когда битовое поле используется для преобразования данных для интерфейса, а интерфейсу нужен определенный формат данных.

Обмен или совместное использование данных

Другим классом проблем с порядком байтов является программный код, который используется как интерфейс между различными системами; например, драйверы устройств, использующие BE-данные, которые преобразуются в LE-данные для использования с LE-драйвером/адаптером. Кроме того, протоколы TCP/IP/UDP/RPC требуют, чтобы данные передавались в сетевом порядке байтов или в BE. В этих примерах используются канонизированные данные. Сама идея заключается в том, что можно сделать интерфейс, который определял бы порядок байтов в данных, с которыми должен работать. Например, драйвер PCI-устройства определяет порядок LE как каноническую форму в большинстве случаев. Программный код, использующий сеть, использует в качестве канонической формы BE.

В основном, подобная ситуация является проблемой для взаимодействия между устройствами (драйвер устройства -> устройство), сетевых приложений или приложений, которые совместно используют данные, разбитые на сегменты размером больше 1 байта.

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

Например, адреса IPv4 и номера TCP-портов в TCP/IP-заголовке обрабатываются как 32-битные беззнаковые целые числа (integer) и 16-битовые целые числа соответственно. Эти данные должны быть представлены в порядке байтов, который используется на конечном компьютере-хосте (точнее, порядке байтов, который использует операционная система, под чьим управлением работает компьютер), поскольку над этими данными выполняются математические операции. Перед отправкой другому получателю данные должны быть преобразованы в BE, а при получении - преобразованы из BE. Для выполнения этого преобразования в программном коде содержится набор процедур, которые принимают значение и конвертируют порядок байтов хоста в BE-порядок и наоборот. Фактически, эти процедуры реализованы в POSIX. К этим процедурам относятся htonl, ntohl, htons и ntohs (буква "s" указывает на тип short, а буква "l" указывает на 32-битную величину).

Прикладные программы должны иметь свою определенную каноническую форму представления данных; приложение должно определить, что данные либо не будут совместно использоваться, либо предоставить утилиты для преобразования порядка байтов. XDR (eXternal Data Representation, внешнее представление данных) является одним из протоколов, который предоставляет канонический формат данных для совместного использования данных на гетерогенных системах. На момент написания этой статьи не планировалось совместное использование системных данных между AIX BE-системой и AIX LE-системой.

Проблемы с порядком байтов, возникающие при обращении к внешнему устройству ввода/вывода, могут быть ликвидированы различными аппаратными и программными решениями, что усложняет портирование драйверов устройств с PowerPC на системы IA (Intel architecture) или Alpha. Хотя PowerPC поддерживает модель хранения данных BE, его шины ввода/вывода (как IBM MicroChannel, так и стандартный PCI) работают на LE. В системах RS/6000 контроллер ввода/вывода, который является мостом между системной шиной и шинами ввода/вывода самого контроллера, предоставляет функцию управления данными, которая преобразует LE в BE (и наоборот) при чтении или записи на устройство. Эта функция управления данными используется для данных, работающих в модели DMA (Direct Memory Access, прямой доступ к памяти), PIO (Program I/O, программный ввод/вывод) или MMIO (Memory-Mapped I/O, ввод/вывод отображаемых данных). В сущности, контроллер ввода/вывода обрабатывает данные как потоки байтов так, что байт 0 в системе переходит в байт 0 в вводе/выводе, байт 1 переходит в байт 1 и т.д. Поэтому, прежде чем передавать поток байтов на ввод/вывод, необходимо переставить некоторые байты местами.

Для обратного упорядочивания байтов при взаимодействии с BE-устройствами AIX предоставляет несколько PIO-макросов. (Большинство устройств ввода/вывода используют LE-порядок байтов; есть, конечно и устройства, работающие с BE-порядком, но их шина все равно использует LE-порядок.)

Большинство зависимостей от порядка байтов в коде возникает из-за обращения к данным как к типам, которыми они не являются. Примером таких действий является обращение к внутренним байтам многобайтового элемента данных, обращение к нескольким элементам данных как к одному большому элементу данных, объявление множества битовых полей в элементе данных, приведение типов данных, использование структуры данных типа union. При портировании программного кода на систему с другим порядком чтения/записи байтов все эти примеры могут стать причиной появления ошибочных результатов и/или отказа системы.

Другими источниками зависимости от порядка байтов являются попытки предугадать порядок байтов, используемый платформой, на которой это приложение будет использоваться. Например, AIX предполагает, что его процессор поддерживает модель хранения данных в BE-порядке. Взаимодействуя со своими PCI-устройствами, которые поддерживают модель хранения данных в LE-порядке, AIX может вызывать функции преобразования порядка байтов (для обратного упорядочивания порядка байтов в структуре данных).

При портировании на платформу с другим порядком байтов во время перекомпиляции обычно создается код с правильным порядком байтов. Однако обычно следует выявить программный код, зависимый от порядка байтов (либо вручную либо при помощи инструментов типа lint) и вручную изменить его, чтобы избавиться от всех проблем с порядком байтов. При портировании кода, разработанного для AIX, следует изменить машинно-независимый код в целях предотвращения возникновения зависимости от порядка байтов; в случае, если проблемы с порядком байтов не удается быстро решить, можно переписать машинно-зависимые сегменты кода с учетом LE.

Можно выбрать решение: изменить структуру данных или изменить способ, при помощи которого программный код обращается к структуре данных (сделав тем самым код независимым от порядка байтов). Отслеживание структур данных и контроль способов обращения программ к данным являются правилами "хорошего тона" в программировании.

Основные характеристики LE- и BE-моделей хранения данных приведены ниже.

  • При BE-порядке обращение к отдельным байтам многобайтового элемента данных от наиболее старшего (значимого) элемента данных к самому младшему (менее значимому) байту ("слева направо"), выполняется точно так же, как при обращении к элементам данных ("слева направо").
  • При LE-порядке обращение к элементам данных и к отдельным байтам сложного элемента данных происходит в противоположном направлении.
  • Начальный адрес элемента данных в обеих моделях хранения LE и BE является одинаковым.
  • В BE- и LE-моделях данных обращение к отдельным байтам многобайтового элемента данных выполняется в противоположных направлениях.
  • Для однобайтовых элементов данных независимость от порядка байтов означает отсутствие последовательных символов в начальных адресах в LE- и BE-режимах.
  • Порядок байтов не имеет значения, если к элементу данных обращаются как к тому типу, которым он и является.
  • Зависимость от порядка байтов становится возможной проблемой тогда, когда к внутренним байтам и/или вложенным элементам данных обращаются по отдельности, или, наоборот, к нескольким несвязанным друг с другом элементам данных обращаются как к одному целому.
  • Упаковка битовых полей в один элемент данных может стать проблемой, если данные должны храниться на постоянном запоминающем устройстве, которое будет использоваться компьютером с другим порядком байтов. Но если данные не используются одновременно BE- и LE-компьютерами, такая ситуация не является проблемной. Внутренние местоположения битовых полей в элементе данных не являются ограничивающим фактором для использования этого элемента данных в BE- и LE-моделях, если к битовым полям обращаются по заранее определенным правилам. Хотя программный код будет выполняться правильно (для своего порядка байтов), возможно, придется изменить комментарии, ассоциированные с этим программным кодом, чтобы представлять битовые шаблоны в противоположном порядке.


В начало


Соглашения по вызову функций

Архитектура AIX предоставляет хорошо определенный набор соглашений по передаче параметров и вызову функций. Эти соглашения одинаковы для 32-битных и 64-битных приложений. Таблица 1.4, приведенная ниже, иллюстрирует обычное использование этих соглашений.


таблица 1.4

Если требуется больше восьми параметров, то дополнительные значения хранятся в стеке. Первые восемь передаваемых параметров, передаваемые в регистр общего назначения, не хранятся в стеке.

Заметим, что если функции передается параметр с плавающей точкой, то он записывается в регистр для чисел с плавающей точкой и в регистр общего назначения. Первый FP-параметр (floating point parameter, параметр с плавающей точкой) хранится в FP1, второй параметр хранится в FP2 и т.д. В качестве примера рассмотрим фрагмент программного кода на C:

float fvar = 2.3;
printf( "x = %f", fvar );

В этом случае значение переменной fvar будет храниться в регистре с плавающей точкой 1. В 64-битном приложении содержимое регистра общего назначения 4 будет также содержать fvar. (Регистр 3 содержит указатель на строку форматирования.) Теперь вызываемая функция сможет получить доступ к параметру либо через регистр для чисел с плавающей точкой, либо через регистр общего назначения. Значение, которое возвращает функция, передается в регистр 3.



В начало


Инструменты

64-битный lint

AIX предоставляет полную поддержку 64-битного анализатора исходного кода (lint), который входит в поставку операционной системы. Кроме того, версия инструмента lint под любую стандартную операционную систему UNIX, с полным набором вспомогательных заголовочных файлов и библиотек доступна по этой ссылке. Вспомогательный документ, который поможет при решении проблем, связанных с портированием на 64-битные платформы, также находится здесь.



Ресурсы

  1. Migrating Tru64 Applications to AIX (EN): оригинал статьи.
  2. Разработка приложений для AIX на C и C++ (EN),
  3. Руководство по переходу на AIX Version 4.3 (EN).
  4. Документация по AIX (EN).
  5. Endianness in Solaris (Steven Zucker, SunSoft Report, февраль 1998г.) (EN): статья о порядке байтов в Solaris.
  6. Endian-Neutral Software, Part 1 (James R. Gillig,Dr. Dobb's Journal, октябрь 1994) (EN): первая часть статьи, посвященной разработке ПО, не зависящего от порядка байтов.
  7. Endian-Neutral Software, Part 2 (James R. Gillig,Dr. Dobb's Journal, ноябрь 1994) (EN) : вторая часть статьи, посвященной разработке ПО, не зависящего от порядка байтов.
  8. IBM Corp., AIX Kernel Extensions and Device Support Programming Concepts (EN): статья о принципах разработки расширений ядра и поддержки устройств в AIX
  9. IBM Corp., POWERstation and POWERserver: Hardware Technical Information General Architecture (EN): статья с общей информацией о POWER-архитектуре.
  10. Раздел developerWorks AIX and UNIX содержит сотни информативных статей для читателей начальной, средней и высокой квалификации.
  11. Блоги developerWorks.
  12. Команда IBM developerWorks проводит по всему миру сотни бесплатных технических консультаций.
  13. IBM trial software: ознакомительные версии программного обеспечения для разработчиков, которые можно загрузить прямо со страницы сообщества developerWorks.
  14. Safari bookstore: сайт магазина книг по ИТ.


Об авторах

Гарри Р. Хук (Gary R. Hook) - старший технический консультант в IBM, оказывающий поддержку ISV в разработке приложений, портировании и решении технических вопросов. Его профессиональный опыт связан главным образом с разработкой Unix-приложений. После прихода в IBM в 1990 году он работал в центре технической поддержки по AIX в Саутлейке, штат Техас, обеспечивая консалтинговую и техническую поддержку клиентов, в основном по архитектуре приложений на AIX. Живя в Остине, Гарри был членом команды разработчиков ядра AIX с 1995 по 2000 годы, специализируясь на компоновщике, загрузчике и инструментах разработки приложений общего назначения на AIX. С ним можно связаться по электронной почте ghook@us.ibm.com.


Вандана Кумар (Vandana Kumar) ведущий технический консультант IBM в ISV Enablement organization. Ее обязанности включают помогать ISV получать преимущества от новых технологий IBM. Она имеет степень бакалавра, полученную в Indian Institute of Technology, Roorkee и степень магистра в Electrical Engineering, полученную в Wayne State University. Она написала несколько статей по портированию и настройке приложений под AIX. Вы можете обратиться к ней по адресу vkumar@us.ibm.com.




Выскажите мнение об этой странице


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



 


 


 


Поделиться этой статьей:

забобрить забобрить memori сохранить в memori




В начало


IBM, логотип IBM, и AIX зарегистрированные торговые марки International Business Machines Corporation в Соединенных Штатах Америки и других странах. UNIX зарегистрированная торговая марка The Open Group в Соединенных Штатах Америки и других странах. Названия других компаний, их продуктов или услуг могут быть торговыми марками других компаний. Другая компания, продукт или название услуги могут быть торговыми марками или знаками обслуживания, принадлежащими иным физическим или юридическим лицам.

IBM обладает всеми авторскими правами касательно информации, расположенной на developerWorks. Использование информации приведенной на этом ресурсе без явного письменного разрешения от IBM или первоначального автора запрещены. Если Вы желаете использовать информацию с developerWorks, пожалуйста воспользуйтесь регистрационной формой для того, чтобы связаться с нами запрос на использование материалов developerWorks Россия.
    IBM в России Конфиденциальность Контакты