2009-06-22 5 views
2

Если я использую mmap для записи uint32_t, сможем ли я столкнуться с проблемами с соглашениями с большим эндиантом/маленьким концом? В частности, если я напишу некоторые данные на машине большого конца, буду ли я сталкиваться с проблемами, когда я пытаюсь прочитать эти данные на маленькой машине?mmap big endian vs. little endian

ответ

2

Да.

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

Как переносимый формат данных на разных компьютерах, я бы рассмотрел что-то более высокий уровень абстракции, такой как JSON или даже XML, который не привязывает формат данных к конкретной реализации. Но это действительно зависит от ваших конкретных требований.

5

Если вы используете mmap, вероятно, вас беспокоит скорость и эффективность. У вас в основном есть несколько вариантов.

  1. Оберните все свои чтения и записи с помощью функций htonl, htons, ntohl, ntohs. Вызов метода htonl (host to network) в Windows будет преобразовывать данные с маленького endian в big endian. На других архитектурах это будет noop. Эти преобразования имеют накладные расходы, но в зависимости от ваших операций они могут быть или не быть значительными. AFAIK, это подход, используемый SQLite.
  2. Другой вариант - всегда записывать данные в формате хоста и предоставлять процедуры, если пользователям необходимо перенести данные на разных платформах. Базы данных обычно читают и записывают данные в формате хоста, но предоставляют такие инструменты, как bcp, которые будут записывать либо в ASCII, либо в сетевой порядок байтов.
  3. Вы можете пометить заголовок своего файла байтом порядка байтов. Когда ваша программа запустится, она сравнит свой порядок байтов с порядком байта файла и при необходимости предоставит любой перевод. Это часто бывает полезно для простых форматов данных, таких как UTF-16, но не для форматов, где у вас есть несколько типов переменной длины.

Кроме того, если вы делаете такие вещи, как префикс длины или смещение файлов, у вас может быть смесь 32-битных и 64-битных указателей. 32-битная платформа не может создать вид mmap размером более 4 ГБ, поэтому маловероятно, что вы будете поддерживать размер файлов более 4 ГБ. Такие программы, как rrdtool, используют этот подход и поддерживают гораздо большие размеры файлов на 64-битных платформах. Это означает, что ваш двоичный файл не будет совместим на всех платформах, если вы использовали размер указателя платформы внутри вашего файла.

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

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

+0

У нас есть аналогичные проблемы, за исключением того, что мы решили, что заказ на байты в Intel является самым естественным способом хранения данных: почти все наши клиенты используют серверы Linux (Intel) или серверы Windows (Intel, конечно). Большой эндиан выходит из моды. –