char *initstate(unsigned int seed, char *state, size_t n);
Инициализирует массив
state
информацией для использования при генерации случайных чисел,
seed
является начальным значением, как для
srandom
, а
n
является числом байтов в массиве
state
.
n
должен равняться одному из значений 8, 32, 64, 128 или 256. Большие значения дают лучшие последовательности случайных чисел. Значения меньше 8 заставляют
random
использовать простой генератор случайных чисел, сходный с
rand
.
Значения больше 8, не равные одному из значений в списке, округляются до ближайшего подходящего значения.
char *setstate(char *state);
Устанавливает внутреннее состояние в соответствии с массивом
state
, который должен быть инициализирован посредством
initstate
. Это позволяет переключаться по желанию между различными состояниями, предоставляя множество генераторов случайных чисел.
Если
initstate
и
setstate
никогда не вызывались,
random
использует массив внутреннего состояния размером 128.
Массив
state
непрозрачен; вы инициализируете его с помощью
initstate
и передается функции
random
посредством
setstate
, но в другом отношении вам не нужно заглядывать в него. Если вы используете
initstate
и
setstate
.
srandom
вызывать не нужно, поскольку начальное значение включено в информацию о состоянии.
ch12-random.c
использует эти процедуры вместо
rand
. Используется также обычная методика, которая заключается в использовании в качестве начального значения генератора случайных чисел времени дня, добавленного к PID.
1 /* ch12-random.c --- генерация вращения костей с использованием random. */
61 j = random % 6; /* использовать диапазон 0 <= j <= 5 */
62 printf("+-------+\n");
63 for (k = 0; k < 3; k++)
64 printf("|%s|\n", die_faces[(j * 3) + k]);
65 printf("+-------+\n\n");
66 }
67
68 return 0;
69 }
Включение PID
в состав начального значения гарантирует, что вы получите различные результаты, даже если две программы будут запушены в течение одной и той же секунды.
Поскольку она создает последовательности случайных чисел лучшего качества,
random
является более предпочтительной по сравнению с
rand
, и GNU/Linux и все современные системы Unix ее поддерживают.
12.6.3. Особые файлы
/dev/random
и
/dev/urandom
Как
rand
, так и
srandom
являются генераторами псевдослучайных чисел. Их вывод для одного и того же начального значения является воспроизводимой последовательностью чисел. Некоторым приложениям, подобным криптографическим, необходимо, чтобы их случайные числа были действительно (более) случайными. С этой целью ядро Linux, также как различные BSD и коммерческие Unix системы предусматривают специальные файлы устройств, которые предоставляют доступ к «энтропийному пулу» случайных битов, которые ядро собирает от физических устройств и других источников. Из справочной страницы random(4):
/dev/random
[Байты, прочитанные из этого файла, находятся] внутри предполагаемого числа шумовых битов в энтропийном пуле,
/dev/random
должен подходить для использования в случаях, когда необходим высокий уровень случайности, таких, как одноразовая генерация ключа или блока памяти. Когда энтропийный пул пустой, чтение
/dev/random
будет блокироваться до тех пор, пока не будет собран дополнительный шум окружения.
/dev/urandom
[Это устройство будет] возвращать столько байтов, сколько затребовано. В результате, если нет достаточной энтропии в энтропийном пуле, возвращаемые значения теоретически уязвимы для криптографической атаки алгоритма, использованного драйвером. Знание того, как это сделать, недоступно в современной не секретной литературе, но теоретически возможно существование подобной атаки. Если для вашего приложения это представляет проблему, вместо этого используйте
/dev/random
.
Для большинства приложений чтения из
/dev/urandom
должно быть вполне достаточно. Если вы собираетесь написать криптографические алгоритмы высокого качества, следует сначала почитать о криптографии и случайности; не полагайтесь здесь на поверхностное представление! Вот еще одна наша программа для бросания костей, использующая
/dev/urandom
:
1 /* ch12-devrandom.с --- генерирует бросание костей, используя /dev/urandom. */