srand#
זריעת מחולל המספרים הפסבדו־אקראיים.
srand מגדיר את המצב הפנימי של ה־PRNG ש־rand שואב ממנו. קראו לו עם שלם מפורש כדי לקבל זרם בר־שחזור, או קראו לו ללא ארגומנט כדי לזרוע מחדש ממקור האנטרופיה הטוב ביותר שהפלטפורמה מציעה. מאז Perl 5.14 srand מחזיר את הזרע שבו השתמש, כך שתוכלו לרשום אותו ולשחזר את אותה ריצה מאוחר יותר.
תקציר#
srand EXPR
srand
מה מקבלים בחזרה#
הזרע שהותקן, כשלם. עבור srand($n) ערך ההחזרה הוא $n (לאחר הקטימה הרגילה לשלם). עבור srand() ללא ארגומנט ערך ההחזרה הוא הזרע שנבחר אוטומטית שנשאב מאנטרופיית המערכת - לכדו אותו אם תרצו אי פעם לשחזר את הריצה.
my $seed = srand(); # auto-seed, remember what we used
warn "seed for this run: $seed\n";
לפני Perl 5.14 srand לא החזיר דבר שימושי. קוד שמסתמך על החזרת הזרע צריך להכריז על הגרסה המינימלית:
use v5.14; # so srand returns the seed
מצב גלובלי#
srand משנה PRNG יחיד שמשתרע על כל התהליך. כל קריאה עוקבת ל־rand באותו תהליך - מכל חבילה, כל מודול, כל הקשר ללא־thread - קוראת מאותו מצב יחיד. אין RNG לכל־חבילה או לכל־תחום. השלכות:
קריאה ל־
srand($k)בכל מקום בתוכנית משפיעה על כל קריאה מאוחרת ל־rand, כולל אלה בתוך מודולים שלא כתבתם.שני תהליכים שקוראים ל־
srand($k)עם אותו$kמפיקים זרמיrandזהים. זה הבסיס לבדיקות ברות־שחזור והסיבה שעליכם לזרוע מחדש לאחרfork.אם
srandלעולם אינו נקרא במפורש, הוא נקרא במשתמע ללא ארגומנט בפעם הראשונה ש־randמופעל.
דוגמאות#
מקרה בדיקה בר־שחזור עם זרע מפורש - אותו קלט, אותו רצף, בכל ריצה:
srand(42);
my @sample = map { rand() } 1..5; # identical on every invocation
זריעה מ־time() לאקראיות בעלת התנגשות נדירה על פני ריצות נפרדות שהחלו בשניות wall-clock שונות. זה הדפוס הקלאסי; הוא אינו ברמה קריפטוגרפית:
srand(time() ^ $$); # time XOR pid, old-school spread
דפוס שמירת־זרע, שחזור־זרע לבדיקה שבוחרת תת־קבוצה אקראית מהמקרים שלה אך רושמת מספיק כדי לשחזר כל כישלון:
my $seed = srand(); # auto-seed, capture it
eval { run_randomised_tests() };
if ($@) {
warn "FAILED with seed=$seed - reproduce with: srand($seed)\n";
die $@;
}
זריעה מחדש לאחר fork כדי שההורה והילד לא ישתפו זרם:
my $pid = fork();
die "fork: $!" unless defined $pid;
if ($pid == 0) {
srand(); # child gets fresh entropy
exec_child_work();
}
שני זרמים בלתי תלויים מאותו זרע - שימושי כשרוצים נקודת בדיקה וחידוש, או diff של שתי ריצות שהתפצלו לאחר נקודת החלטה:
srand(12345);
my @first = map { rand() } 1..10;
srand(12345);
my @second = map { rand() } 1..10; # identical to @first
מקרי קצה#
צורה ללא־ארגומנט זורעת אוטומטית עם האנטרופיה הטובה ביותר הזמינה. ב־Linux זה שואב מ־
/dev/urandom(אוgetrandom(2)). הזרע רחב מספיק כך שיש להתייחס אליו כאל אטום, לא כשלם קטן.אל תקראו ל־
srand()ללא ארגומנטים יותר מפעם אחת לתהליך. המצב הפנימי של ה־PRNG כבר נושא יותר אנטרופיה מכל זרע יחיד יכול לשחזר, אז זריעה מחדש מאבדת אקראיות במקום להוסיף אותה. שתי הסיבות הלגיטימיות לקרוא לו שוב ושוב הן (א) עם זרע מפורש לשחזור, ו(ב) פעם אחת בכל ילד לאחרfork.ארגומנטים עשרוניים נקטמים בשקט לשלם.
srand(42)ו־srand(42.9)מתקינים את אותו זרע. תמיד העבירו שלם כדי שהכוונה תהיה ברורה.אותו זרע ⇒ זרם
randזהה. זה כל הפואנטה לבדיקות; זוהי כל הבעיה לאבטחה.לא בטוח קריפטוגרפית.
rand/srandמשתמשים ב־PRNG מהיר לא־קריפטוגרפי. אל תשתמשו בהם ליצירת טוקני session, nonces, מפתחות, saltים של סיסמאות, או כל דבר שיריב לא יוכל לחזות. השתמשו ב־[Crypt::URandom][cu] או קראו מ־/dev/urandomישירות.משתנה הסביבה
PERL_RAND_SEED. אם מוגדר לשלם אי־שלילי בעת אתחול התהליך,srand()ללא ארגומנט (כולל הקריאה המשתמעת שמופעלת על ידי ה־randהראשון) מתקין זרע דטרמיניסטי שנגזר מאותו ערך. הגזירה אינה מוגדרת בכוונה; רק שחזור אותו־ערך־אותו־בינארי־אותו־קוד מובטח. מיועד לדיבוג וניתוח ביצועים. המשתנה נקרא פעם אחת באתחול; שינוי%ENVמאוחר יותר אין לו השפעה על התהליך הנוכחי.Threads (
use threads): כל שיבוט מפרש מקבל מצב PRNG משלו. זריעה ב־thread אחד אינה משפיעה על אחר.תחום הזרע: אין דרך לבצע
localעל מצב ה־PRNG. אם ספרייה שאתם קוראים לה ביניים מבצעתsrand, הזרם שלכם מופרע. לכדו ושחזרו ידנית אם זה משנה.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי. PERL_RAND_SEED מכובד עם אותו חוזה ״לא מוגדר בכוונה אך בר־שחזור״ כמו perl5.
ראו גם#
rand- צרכן המצב ש־srandמתקין; שואב את הערך הבא מהזרם הזרועtime- שניות מאז ה־epoch; מקור הזרע הקלאסי מהיר־ומלוכלך לקוד שאינו אבטחתי (srand(time() ^ $$))[
Crypt::URandom][cu] - בתים אקראיים בטוחים קריפטוגרפית ממאגר האנטרופיה של מערכת ההפעלה; השתמשו בו, לא ב־rand, לטוקנים ומפתחות[
Math::Random::MT][mt] - PRNG של Mersenne Twister עם מצב בלתי תלוי משלו, כשאתם זקוקים לזרם שני שאינו מופרע על ידי קריאות ספרייה ל־randperlrun- מתעד את משתנה הסביבהPERL_RAND_SEEDוכפתורי אתחול אחרים