Selecting a Unique Identifier in C for an Embedded Application

Refresh

December 2018

Views

1.4k time

4

I am currently trying to implement an algorithm to select a unique (16-bit) identifier. The challenge is to do this in an fast way that doesn't use too much memory. The list of currently used identifiers is determined through scanning an external Flash device via a sequence of SPI transactions and is therefore a relatively slow process. Also, the algorithm will be running on a small-ish microcontroller, so I can't really just read all the entries into RAM and process them there.

The thoughts I've had so far are:

  1. Pick a number, then scan through the list and see if it's used. Rinse and repeat. Suffers from being rather slow (particularly if there are a lot of files).
  2. As above, but pick the number using a pseudo-random number generator with an appropriate seed. This has the advantage that it's less likely that there will be such large numbers of iterations.
  3. Scan through the list and populate an array with all the entries found. Sort it and then it becomes trivial. This could use an enormous amount of memory.
  4. Use an enormous (okay, ridiculously enormous) bit mask. Not really practical.
  5. Accept that the life-time of the tool is such that it will be thrown away or 'formatted' long before it has written 65534 files to the Flash, so just store the highest value used so far in the Flash or Backup memory and keep incrementing. In all honesty, this would probably work quite well for this specific application.

At the moment, I'm verging towards using either the second one or the fifth, but I'd be interested to know if anyone has any other thoughts. I'd like to think that there's an algorithm similar in form to a CRC that could be used to process each number in turn and give a fair idea of a number that hasn't been used, but I've no idea how this might work.

12 answers

4

Если не хватает оперативной памяти для реализации растрового изображения, достаточно большой для 64К записей, количество сканирований через FLASH, чтобы найти неиспользуемый идентификатор может быть уменьшен при использовании меньшего, временное растровое изображение для каждого сканирования. 16-байтовый битовый массив может записывать найденные идентификаторы в диапазоне 0-255 на первый проход, 256-511 на второе сканирование и т.д., в конце каждого сканировании, если есть по крайней мере один немаркированные бит в битовой карте вы повторно сделано. Я считаю, что это будет хорошо работать в сочетании с использованием случайного отправную диапазона.

С другой стороны, если бы я имел высокую уверенность в варианте 5 я мог бы просто пойти с этим.

1

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

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

[EDIT] Поскольку вы озабочены столкновениями, должны быть какие-то данные, где может произойти столкновение, например, в именах файлов или некоторые такие. Если очевидный подход (создание файла и проверить, существует ли он) слишком медленно, и у вас есть огромные пробелы в «карте распределения», а затем сгенерировать случайный идентификатор и проверить с этим. Это позволит вам найти неиспользуемые с помощью нескольких итераций.

0

Сколько оперативной памяти у вас есть? Это немного трудно сказать, «встроенный» может означать так много в эти дни. :) Растровый требуют 8192 байт, на протяжении поколения, а также гарантировать отличные результаты каждый раз.

Я также рассмотрел своего рода «разреженный» битовой карты, но я не знаю, подходящую структуру данных от руки, но может быть стоит исследовать.

0

Об CRC как алгоритм интерес ...

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

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

Лучше всего то, кажется, 5 из списка.

Если вы предприимчивы ...

и, если вы можете повторно номер ваших идентификаторы (т.е. изменить выделенный идентификатор другого незанятого ID), вы можете запустить «дефрагментацию» вид итерации один раз в некоторое время, чтобы переместить все выделенные идентификаторы для снижения значения и найти самую высокую свободную Идентификационный номер для следующего распределения. Это помогло бы вспомнить общее число распределений и высвобождает поступали с запуском последнего такого «Defrag». Выделяет приращение последовательно, начиная с 0.

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

nik
1

Используйте Максимальный линейный Обратная сдвиговый регистр и сохранить последнее значение , которое вы раздавали. ЛРСОС будет, учитывая конкретную отправную точку (не включая ноль) даст вам все номера в последовательности 1..2 ^ п, в порядке псевдослучайной. Если вы начинаете с элементом -го, вы всегда получите тот же к + 1 - е элемент. Реализация крошечная:

if (IsEven(sequence)) {
    sequence /= 2;
}
else {
    sequence = (sequence / 2) ^ feedback;
}

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

С другой стороны, почему вы не просто подсчет и хранение последнего номера выдаваемый?

0

Другим вариантом было бы сохранить файл идентификаторами на флэш-диске. Таким образом, вы не запрашивая все возможности каждый раз. Если вы хотите случайные идентификаторы, затем рандомизации файл. Храните смещение до конечной в качестве первого числа в файле. Когда вам нужно, удалите последний из файла, и когда вы бесплатно один, добавьте его обратно в файл. С офсетной и флэш-диск, он должен быть почти постоянной работы времени независимо от того, количество идентификаторов осталось. В качестве бонуса, смещение в начале покажет вам, сколько идентификаторов вы оставили, если вам нужно знать, что в любой момент. Недостаток будет то, что вы должны получить доступ к флэш-памяти для каждого ID (постоянного времени, но до сих пор доступ), и как обработать случай ошибки, если файл не существует.

0

Продолжайте рассчитывать бегущий последовательный ID.
Запустите ID через MD5.
Используйте самые низкие 16 бит.

Теория заключается в том, что MD5 создает различные хэш для каждого входа. Самые низкие 16 битов должны быть так же, как «случайный», как весь хэш.

0

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

5

Я думаю , что у вас есть несколько вариантов здесь, но еще один , чтобы рассмотреть это Bloom фильтр . Это имеет возможность ложных срабатываний (например , вы можете исключить из идентификатора , как уже используется , даже если он не был) , но это может позволить вам выбрать точное количество пространства , которое вы можете посвятить эти данные.

0

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

0

Я хотел бы попробовать вариант 3. Вместо того чтобы хранить отсортированный массив значений, я бы хранить отсортированный массив диапазонов.

1

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

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

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