Влияет ли srand(getpid()) на формат/структуру?

Этот вопрос быстрый :). Я знаю, что srand() используется для заполнения генератора случайных чисел, чтобы предотвратить генерацию одной и той же последовательности случайных чисел. Точно так же я знаю, что getpid() «должен вернуть идентификатор процесса вызывающего процесса».

( http://pubs.opengroup.org/onlinepubs/009695399/functions/getpid. HTML )

Из-за того, что идентификатор процесса в конечном итоге отличается каждый раз, когда вы запускаете мою программу (программу, в которой производитель и потребитель общаются через общую память), PID также будет другим, что дает идеальное начальное значение. Я установил диапазон для случайных чисел rand() % (100-1) + 1.

Предоставляет ли srand(getpid()) случайные числа в определенном формате?

Для полноты, вот раздел кода, к которому относится мой запрос:

srand(getpid());

while(x == 0)
{      
        if(*randNum == 101)
        {      
                *randNum = rand() % (100 - 1) + 1;
                *pidNum = getpid();

                printf("priority: %d Process ID: %d \n", *randNum, *pidNum);

                x = 1;
        }   
        else
        {      
                *randNum++;
                *pidNum++;
        }   
}   

person viKK    schedule 29.07.2013    source источник
comment
Каким будет формат случайных чисел для вас?   -  person Jens Gustedt    schedule 29.07.2013


Ответы (2)


Я не совсем уверен, что вы подразумеваете под конкретным форматом. Но getpid() не является хорошим выбором в качестве начального значения. PID находятся в довольно небольшом диапазоне «беззнакового» пространства, и их легко угадать.

Если вы не заботитесь о том, чтобы люди могли угадать ваше начальное число, time(NULL) — гораздо лучший выбор в качестве начального значения.

person Guillaume    schedule 29.07.2013
comment
за исключением случаев, когда два процесса могут выполняться одновременно. Я думаю, что трудно найти «в целом хорошее» семя (но, конечно, вы правы насчет использования getpid()) - person Ingo Leonhardt; 29.07.2013
comment
srand(time(NULL) ^ getpid()) — это один из подходов, но если вы так сильно заботитесь о непредсказуемости и/или высококачественных псевдослучайных числах, вам, вероятно, следует использовать что-то другое, кроме srand и rand. - person Keith Thompson; 29.07.2013
comment
@IngoLeonhardt получить «в целом хорошее» семя совершенно тривиально. Прочитайте sizeof(int) байт из /dev/urandom (или /dev/random, если хотите) в системе Linux. Другие операционные системы предлагают аналогичные возможности. В Windows CryptGenRandom будет работать очень хорошо (или RtlGenRandom если вы чувствуете себя немного более предприимчивым и не желаете открывать поставщика криптографических услуг). - person Nik Bougalis; 29.07.2013
comment
@Nik, спасибо, я не думал об этом - person Ingo Leonhardt; 29.07.2013
comment
Спасибо за все ответы, ребята :). Мой вопрос о формате был больше о том, как он будет выглядеть на выходе. Причина, по которой я не смог протестировать это, заключалась в том, что я постоянно получал ошибки сегментации и не имел времени для правильной отладки. Поскольку вывод представляет собой список приоритетов, имитирующий задания на печать (процессы, созданные производителем, прикрепленные к случайному числу, детализирующему «имя/идентификатор» задания на печать), я просто хотел выяснить, будут ли они выглядеть как значения PID или нет, и теперь я понимаю . Спасибо еще раз! - person viKK; 29.07.2013
comment
time намного хуже, чем getpid; это не только более предсказуемо; на самом деле она будет повторяться десятки или даже сотни раз, если вы быстро вызовете программу. Единственные вещи, которые вы должны использовать в качестве случайного начального числа, — это либо поле tv_nsec из struct timespec, возвращаемое clock_gettime, либо байты из /dev/urandom. - person R.. GitHub STOP HELPING ICE; 29.07.2013
comment
@Р. время не более предсказуемо, чем getpid. В большинстве систем существует только 32K возможных значений для PID. Вы можете найти pid, просто запустив ps или просмотрев /proc. Ваше замечание по поводу clock_gettime интересно, но семя просто беззнаковое, и большинство системных часов не имеют разрешения nsecs, так что это, вероятно, не очень хорошая идея. Чтение из /dev/urandom определенно лучше. Я просто привел пример простого, который лучше, чем getpid, но я ясно сказал, что его легко догадаться. - person Guillaume; 29.07.2013

Нет двух запущенных процессов с одинаковым PID, это точно, но нет гарантии, что новый процесс не получит тот же PID, что и только что завершившийся процесс. Обычно PID постоянно увеличивается, но рано или поздно он переполнится (например, в Linux максимальный PID по умолчанию равен 32'768), и тогда PID, которые уже использовались ранее, будут перезапущены (некоторые системы также перезапускаются раньше, например, как они зарезервировали диапазоны PID для различных процессов и т. д.).

Следующая проблема заключается в том, что rand является очень плохим генератором случайных чисел во многих системах (Linux может быть исключением, но ваши теги говорят "UNIX"). BSD даже утверждает это на странице руководства (справедливо для большинства потомков BSD, даже включая MacOS X). Это только для совместимости с кодом, отличным от POSIX. Весь современный код использует вместо этого random. Это намного лучший генератор случайных чисел на большинстве систем (и на других системах он также не хуже, чем rand(), так что вы ничего не теряете, используя его). Если вы не всегда можете сказать наверняка, что ваш код никогда не будет работать ни в одной системе со "слабой rand()" реализацией, использование random является безопасным подходом.

Большинство систем поддерживают вызов srandomdev(), который не является частью стандарта POSIX, но в настоящее время он доступен почти во всех системах. Это инициализирует random, считывая данные из случайного генератора в ядре системы (во многих системах, доступных через /dev/random). Этот генератор случайных чисел генерирует очень хорошие случайные числа и, в зависимости от системного оборудования, может даже генерировать «настоящие случайные числа». Например. многие современные процессоры и некоторые микросхемы материнских плат имеют аппаратные генераторы случайных чисел, которые могут генерировать случайные числа из какого-то «случайного электрического шума», которые почти идеально случайны — если такое оборудование доступно и ядро ​​его поддерживает, оно будет его использовать. для генерации случайных чисел.

person Mecki    schedule 29.07.2013
comment
В Linux rand неизвестно с каких пор совпадает с random. Хотя это хорошая причина предпочесть random, если ваш код должен работать на платформе с плохим rand, безоговорочно говорить, что rand очень плохой, неправильно. - person Daniel Fischer; 29.07.2013
comment
rand не должно совпадать с random по той простой причине, что существует программное обеспечение, основанное на неправильном поведении rand. Рассмотрим приложение, работающее по сети, одна копия работает в Linux, другая — в BSD. Если оба вызывают srand() с одним и тем же начальным числом, они должны выдавать одинаковые случайные числа (это ожидаемое и желаемое поведение), но если Linux действительно изменил rand, чтобы он работал как random, это программное обеспечение сломалось бы. Вот почему rand не было изменено большинством систем, но была введена новая функция random. - person Mecki; 29.07.2013
comment
@Mecki: поведение rand зависит от реализации. Вы не можете полагаться на то, что одно и то же семя создаст одну и ту же последовательность, за исключением одной и той же реализации. Если вам нужна такая гарантия, напишите свою собственную функцию, похожую на rand. Традиционный rand представляет собой 1 строку C, и вы можете просто скопировать и вставить его из стандарта C, но многие реализации используют несколько менее плохие версии, которые вы можете предпочесть скопировать. - person R.. GitHub STOP HELPING ICE; 29.07.2013
comment
Стандарт не говорит, как должен вести себя rand (помимо того, что он выдает псевдослучайные числа в диапазоне от 0 до RAND_MAX), поэтому полагаться на что-либо в отношении его поведения полностью нельзя. RAND_MAX уже меняется между реализациями. - person Daniel Fischer; 29.07.2013
comment
Между прочим, сделать статистически стойкий (что не то же самое, что криптографически стойкий) PRNG очень просто. Некоторое время назад я поэкспериментировал с ним и обнаружил, что даже 32-битный LCG с функцией закалки, примененной к выходным данным, прошел все статистические тесты, которые я мог провести, кроме тех, которые поймали короткий период 2^32. Если вы примените ту же функцию смягчения к старшим 32 битам 64-битного LCG, вы должны получить (статистически) очень сильный и очень быстрый PRNG. - person R.. GitHub STOP HELPING ICE; 29.07.2013
comment
Хорошо, хорошо, rand может быть неплохим генератором случайных чисел во всех системах, но он есть во всех системах на базе BSD, включая Mac OS X, и если вы хотите написать код POSIX, для которого нужны хорошие случайные числа, вам просто не нужно используйте rand, так как вы никогда не можете сказать наверняка, что ваш код не работает в системе, где rand — плохой код. random хорош во всех известных системах. - person Mecki; 29.07.2013
comment
@Mecki: random также является потокобезопасным, тогда как rand нет, но состояние для random совместно используется всеми потоками, поэтому вы не можете получить воспроизводимые результаты, если его используют несколько потоков (какой из них принимает следующее значение в последовательности первым будет зависит от расписания). Кроме того, использование random в библиотеках нецелесообразно, поскольку это будет мешать состоянию/последовательности вызывающей программы. По этим причинам многие проекты застряли на использовании rand_r, качество которого даже хуже, чем rand, и его нельзя значительно улучшить... - person R.. GitHub STOP HELPING ICE; 29.07.2013
comment
@R.. См. man-страницу POSIX для случайных: Потоковые приложения должны использовать erand48(), nrand48() или jrand48() вместо random(), когда требуется независимая последовательность случайных чисел в нескольких потоках. > Эти функции получают свое состояние в качестве входного параметра, поэтому каждый поток/библиотека может иметь свое собственное состояние. - person Mecki; 29.07.2013
comment
@Mecki: Действительно, но эти функции относятся к опции XSI (Unix), а не к базе POSIX, и их API сложен (и их сила ослаблена), поскольку они основаны на массиве шорт, а не на простой 64-битной арифметике. Тривиальный однострочный return (seed = 6364136223846793005ULL*seed + 1) >> 33; (где seed равно uint64_t) является лучшим PRNG, чем эти функции. - person R.. GitHub STOP HELPING ICE; 29.07.2013