Linux программирование в примерах
должен равняться одному из значений 8, 32, 64, 128 или 256. Большие значения дают лучшие последовательности случайных чисел. Значения меньше 8 заставляютnиспользовать простой генератор случайных чисел, сходный сrandom(). Значения больше 8, не равные одному из значений в списке, округляются до ближайшего подходящего значения.rand()char *setstate(char *state);Устанавливает внутреннее состояние в соответствии с массивом
, который должен быть инициализирован посредствомstate. Это позволяет переключаться по желанию между различными состояниями, предоставляя множество генераторов случайных чисел.initstate()Если
иinitstate()никогда не вызывались,setstate()использует массив внутреннего состояния размером 128.random()Массив
непрозрачен; вы инициализируете его с помощьюstateи передается функцииinitstate()посредствомrandom(), но в другом отношении вам не нужно заглядывать в него. Если вы используетеsetstate()иinitstate().setstate()вызывать не нужно, поскольку начальное значение включено в информацию о состоянии.srandom()использует эти процедуры вместоch12-random.c. Используется также обычная методика, которая заключается в использовании в качестве начального значения генератора случайных чисел времени дня, добавленного к PID.rand()1 /* ch12-random.c --- генерация вращения костей с использованием random(). */23 #include <stdio.h>4 #include <stdlib.h>5 #include <sys/types.h>6 #include <unistd.h>78 char *die_faces[] = { /* Управляет ASCII графика! *//* ... как раньше ... */32 };3334 /* main --- выводит N различных граней кубиков */3536 int main(int argc, char **argv)37 {38 int nfaces;39 int i, j, k;40 char state[256];41 time_t now;42/* ... проверка args, вычисление nfaces, как раньше ... */5556 (void)time(&now); /* В качестве начального значения используются время дня и PID */57 (void) initstate((unsigned int)(now + getpid()), state, sizeof state);58 (void)setstate(state);5960 for (i = 1; i <= nfaces; i++) {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 }6768 return 0;69 }Включение PID в состав начального значения гарантирует, что вы получите различные результаты, даже если две программы будут запушены в течение одной и той же секунды.
Поскольку она создает последовательности случайных чисел лучшего качества,
является более предпочтительной по сравнению сrandom(), и GNU/Linux и все современные системы Unix ее поддерживают.rand()12.6.3. Особые файлы
и/dev/random/dev/urandomКак
, так иrand()являются генераторами псевдослучайных чисел. Их вывод для одного и того же начального значения является воспроизводимой последовательностью чисел. Некоторым приложениям, подобным криптографическим, необходимо, чтобы их случайные числа были действительно (более) случайными. С этой целью ядро Linux, также как различные BSD и коммерческие Unix системы предусматривают специальные файлы устройств, которые предоставляют доступ к «энтропийному пулу» случайных битов, которые ядро собирает от физических устройств и других источников. Из справочной страницы random(4):srandom()/dev/random[Байты, прочитанные из этого файла, находятся] внутри предполагаемого числа шумовых битов в энтропийном пуле,
должен подходить для использования в случаях, когда необходим высокий уровень случайности, таких, как одноразовая генерация ключа или блока памяти. Когда энтропийный пул пустой, чтение/dev/randomбудет блокироваться до тех пор, пока не будет собран дополнительный шум окружения./dev/random/dev/urandom[Это устройство будет] возвращать столько байтов, сколько затребовано. В результате, если нет достаточной энтропии в энтропийном пуле, возвращаемые значения теоретически уязвимы для криптографической атаки алгоритма, использованного драйвером. Знание того, как это сделать, недоступно в современной не секретной литературе, но теоретически возможно существование подобной атаки. Если для вашего приложения это представляет проблему, вместо этого используйте
./dev/randomДля большинства приложений чтения из
должно быть вполне достаточно. Если вы собираетесь написать криптографические алгоритмы высокого качества, следует сначала почитать о криптографии и случайности; не полагайтесь здесь на поверхностное представление! Вот еще одна наша программа для бросания костей, использующая/dev/urandom:/dev/urandom1 /* ch12-devrandom.с --- генерирует бросание костей, используя /dev/urandom. */23 #include <stdio.h>4 #include <fcntl.h>