Главные 64-разрядные изменения

Существует много различий между 32-разрядными и 64-разрядными средами в OS X, включая изменения использования инструмента, изменения в размере и выравнивании типов данных, прагм выравнивания и драйверов Набора I/O. В этой главе описываются основных разработчиков изменений, должен знать при портировании кода на 64-разрядный. Необходимо считать эту главу, если Вы решили портировать свой код на 64-разрядный или если Вы пишете новый код с нуля.

Изменения инструментов

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

Изменения типа данных

В этом разделе описываются изменения в размерах типа данных и выравнивании в 64-разрядных исполнимых программах, и объясняет, как эти изменения повлияют на Ваш код.

Размер типа данных и выравнивание

OS X использует две модели данных: ILP32 тех (в который целые числа, long целые числа и указатели являются 32-разрядными количествами), и LP64 (в котором целые числа являются 32-разрядными количествами, и long целые числа и указатели являются 64-разрядными количествами). Другие типы эквивалентны своим 32-разрядным дубликатам (за исключением size_t и немногие другие, которые определяются на основе размера long целые числа или указатели).

В то время как почти весь UNIX и реализации Linux используют LP64, другие операционные системы используют различные модели данных. Windows, например, использует LLP64, в который long long переменные и указатели являются 64-разрядными количествами, в то время как long целые числа являются 32-разрядными количествами. Cray, в отличие от этого, использует ILP64, в который int переменные являются также 64-разрядными количествами.

В OS X выравнивание по умолчанию, используемое для расположения структуры данных, является естественным выравниванием (за немногим исключением отмеченный ниже). Естественное выравнивание означает, что элементы данных в структуре выровненные с промежутками соответствие ширине базового типа данных. Например, int переменная, которая 4 байта шириной, была бы выровненная на 4-байтовой границе.

Таблица 2-1 показывает основе (определенные с помощью компилятора) типы данных и общие межплатформенные типы данных, используемые в OS X, вместе с их размером и выравниванием. Различия LP64 выделяются полужирным.

Табличный 2-1  Размер и выравнивание базовых типов данных в OS X

Тип данных

Размер ILP32

Выравнивание ILP32

Размер LP64

Выравнивание LP64

символ

1 байт

1 байт

1 байт

1 байт

короткий

2 байта

2 байта

2 байта

2 байта

интервал

4 байта

4 байта

4 байта

4 байта

долго

4 байта

4 байта

8 байтов

8 байтов

указатель

4 байта

4 байта

8 байтов

8 байтов

size_t

4 байта

4 байта

8 байтов

8 байтов

долго долго

8 байтов

4 байта

8 байтов

8 байтов

fpos_t

8 байтов

4 байта

8 байтов

8 байтов

off_t

8 байтов

4 байта

8 байтов

8 байтов

В дополнение к этим изменениям в базовых типах данных различные уровни OS X имеют другие типы данных, изменяющие размер или базовый тип в 64-разрядной среде. Самое известное из этих изменений является этим NSInteger и NSUInteger (Типы данных какао), являются 64-разрядными в 64-разрядной среде и 32-разрядными в 32-разрядной среде. Эти изменения описаны в 64-разрядном Руководстве для Разработчиков Углерода, 64-разрядном Руководстве по Переходу для Какао, и Расширениях ядра и Драйверах.

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

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

Влияние типа данных на код

Тип данных и изменения выравнивания влияют на разработчиков в нескольких широких областях.

  • Межпроцессное взаимодействие, сети, общая память и граничные пересечения пользовательского ядра

    При необходимости в 64-разрядном программном обеспечении для передачи с 32-разрядным программным обеспечением (ли по сети, через локальные механизмы IPC, через общую память, или посредством пересечения границы пользовательского ядра всегда), выберите типы данных тщательно. Хорошая практика должна всегда использовать явно измеренные типы данных, такой как uint32_t, вместо универсальных типов данных (такой как long).

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

  • Файлы хранятся на диске

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

    Также можно создать отдельный формат файла, который является определенным для 64-разрядной версии приложения. Для некоторых приложений, создавая новый формат может быть проще, чем поддержание формата совместно используемого файла. Это нужно считать исключением, а не правилом, как бы то ни было.

    Наконец, никогда не недооценивайте удобство универсального обменного формата, такого как XML.

  • Библиотеки

    Все библиотеки, пользовавшиеся 64-разрядными приложениями или расширениями ядра, должны быть перекомпилированы с 64-разрядным компилятором. Если эти библиотеки также необходимы для 32-разрядных приложений или расширений ядра, необходимо пользоваться библиотекой двойной архитектуры (или иметь многократные копии библиотеки).

  • Плагины

    Приложения, которые Вы компилируете как 64-разрядная исполнимая программа, не могут загрузить 32-разрядные плагины непосредственно. Точно так же приложения, которые Вы компилируете как 32-разрядная исполнимая программа, не могут загрузить 64-разрядные плагины.

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

  • Графические интерфейсы пользователя

    Высокоуровневые платформы, используемые для графических интерфейсов пользователя, доступны как 64-разрядные платформы только в OS X v10.5 и позже. Предыдущие версии OS X будут автоматически использовать 32-разрядную версию Вашей исполнимой программы.

  • Различия в выравнивании данных

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

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

Изменения настроек безопасности

В 64-разрядных исполнимых программах, выполняя код в сегментах данных не позволяется. Для достижения этого NX (не выполняются), бит установлен на записях таблицы страниц для штабеля, «кучи», и инициализирован и деинициализирует сегменты данных.

В целом это не должно оказывать влияние на разработчиков, если Вы не делаете что-то нестандартное, такое как запись кода самоизменения. Если Вы пишете код, требующий выполнения на штабеле или в «куче», необходимо явно отметить исполнимое использование страниц mprotect или другие подобные вызовы.