תהליכים

sleep#

השהיית התהליך למספר שניות שלמות.

sleep משהה את ביצוע התהליך הנוכחי למשך EXPR שניות, או - ללא ארגומנט - עד שאות מעיר אותו. הארגומנט נחתך למספר שלם; השהיות תת־שנייה דורשות כלי אחר (ראו להלן). ערך ההחזרה הוא מספר השניות שאכן עברו בשינה, שיכול להיות פחות מהמבוקש אם אות הפסיק את הקריאה.

תקציר#

sleep EXPR
sleep

מה מקבלים בחזרה#

מספר שלם: מספר השניות שבהן התהליך אכן הושעה. בקריאה לא־מופרעת זה שווה לארגומנט (החתוך). אם אות שנמסר במהלך השינה משחרר את הקריאה מוקדם, ערך ההחזרה הוא הזמן הקצר יותר שעבר בפועל. עבור sleep חשוף, הערך הוא מה שהמימוש ישן לפני שאות הגיע.

my $slept = sleep 10;
warn "woken early after $slept s" if $slept < 10;

טיפול בארגומנט#

  • מספר שלם חיובי - המקרה הרגיל. שינה לאותו מספר שניות.

  • לא־שלם (למשל 2.9) - החלק השברי מושלך. sleep 2.9 ישן שתי שניות, לא כמעט שלוש. להשהיות שבריות יש להשתמש ב־Time::HiRes::sleep, Time::HiRes::usleep, או בצורת ארבעת הארגומנטים של select - ראו להלן.

  • מספר שלם שלילי - sleep אינו ישן. הוא פולט אזהרה, קובע את $! (errno), ומחזיר אפס.

  • אפס - sleep 0 מותר, אך עדיין מבצע קריאה לפרימיטיב השינה של הפלטפורמה שבבסיס עם כל תופעות הלוואי הכרוכות בכך. לכן הוא אינו זהה בדיוק לדילוג על הקריאה. בפרט, sleep 0 אינו זהה ל־sleep חשוף ללא ארגומנט.

  • ללא ארגומנט - sleep ללא ארגומנט ישן לאינסוף, עד שאות נמסר. זה נבדל מ־sleep 0.

הפסקה על־ידי אותות#

sleep חוזר מוקדם אם התהליך מקבל אות שמטפלו רץ (או שפעולת ברירת המחדל שלו אינה מסיימת את התהליך). התבנית הקנונית להמתנה חסומה הניתנת לביטול ממקום אחר היא alarm בשילוב עם מטפל אות:

eval {
    local $SIG{ALRM} = sub { die "Alarm!\n" };
    sleep;
};
die $@ unless $@ eq "Alarm!\n";

מכיוון ש־sleep עצמו ממומש בדרך כלל מעל alarm במערכות Unix, בדרך כלל לא ניתן לערבב קריאות alarm ו־sleep באותה תוכנית בלי הפתעות. יש לבחור באחד.

השהיות תת־שנייה#

sleep הוא מספר־שלם־בלבד בעיצובו. להמתנות בדיוק עדין יותר יש להשתמש באחד מאלה:

  • Time::HiRes::sleep($seconds) - מקבל מספר שניות בנקודה צפה. מאז Perl 5.8 Time::HiRes נשלח עם הפצת הליבה.

  • Time::HiRes::usleep($microseconds) - מיקרו־שניות במספר שלם.

  • צורת ארבעת הארגומנטים של select עם שלושת הארגומנטים הראשונים undef:

    select undef, undef, undef, 0.25;   # sleep 250 ms
    
  • syscall אל setitimer(2) אם הפלטפורמה תומכת בכך ונדרשת שליטה הדוקה על טיימרים.

ראו גם POSIX::pause, החוסם את התהליך עד שאות כלשהו מגיע - למעשה sleep חשוף ללא מקסימום המוגדר במימוש.

דוגמאות#

השהיה קבועה:

print "working...\n";
sleep 3;
print "done\n";

לולאת בדיקה עם השהיה הולכת וגדלה:

until (ready()) {
    sleep 1;
}

זיהוי התעוררות מוקדמת:

my $want = 30;
my $got  = sleep $want;
if ($got < $want) {
    warn "interrupted after $got of $want seconds\n";
}

המתנה לאות בלי לבזבז CPU - sleep חשוף משהה עד ש־SIGALRM (או כל אות נתפס אחר) מגיע:

$SIG{USR1} = sub { warn "got USR1\n" };
sleep;                                  # wakes on USR1 delivery

ביטול המתנה ארוכה עם alarm:

eval {
    local $SIG{ALRM} = sub { die "timeout\n" };
    alarm 5;
    sleep 3600;                         # at most 5 seconds really
    alarm 0;
};
alarm 0;
die $@ if $@ && $@ ne "timeout\n";

מקרי קצה#

  • sleep חשוף אינו ישן באמת ״לנצח״. למימוש יש מקסימום - בפועל, כל מה ש־sleep(3) של C שבבסיס או שווה־ערך מקבל - אך לכל מטרה ריאלית הוא חוסם עד שאות מגיע. יש להתייחס אליו כהמתנה לאינסוף.

  • sleep 0 ≠ אין קריאה. קריאת המערכת sleep(0) של הפלטפורמה עדיין רצה. ברוב המערכות זה משחרר את ה־CPU לרגע; אין להסתמך על ההתנהגות הספציפית בין פלטפורמות.

  • sleep מול זמן wall-clock. במערכות ישנות sleep היה יכול לחזור עד שנייה שלמה מוקדם בגלל ספירת שניות גסה. מערכות מודרניות ישנות את הכמות המלאה, אך עלולות לחרוג: המתזמן עלול לא להעיר את התהליך מיד במערכת עמוסה. sleep N מבטיח לפחות N שניות של השהיה בקרנלים מודרניים, לא בדיוק N.

  • ארגומנטים שליליים אינם נקלצים. הם no-op קשיח שקובע את $!. אם מחשבים את הארגומנט, יש לאמת אותו תחילה.

  • ערבוב עם alarm שביר. טיימר ה־alarm וטיימר ה־sleep עשויים להיות אותו משאב. יש לבסס משמעת אחת (או alarm + sleep חשוף, או sleep N פשוט ללא alarms) ולדבוק בה בתוך תוכנית.

  • אותות שרק קובעים דגל עדיין מעירים את sleep. כל אות שמסירתו גורמת למטפל לרוץ מחזיר את השליטה ל־Perl; sleep חוזר אז מוקדם גם אם המטפל עצמו אינו עושה דבר נראה.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • alarm - לקבוע SIGALRM לאחר מספר שניות נתון; הדרך הקלאסית להגביל sleep או כל קריאה חוסמת אחרת

  • select - בצורת ארבעת הארגומנטים שלו עם שלשת readfds/writefds/exceptfds לא־מוגדרת, מספק שינה תת־שנייה

  • wait, waitpid - חוסמים על תהליכי־ילד במקום על זמן

  • Time::HiRes::sleep - שניות בנקודה צפה

  • Time::HiRes::usleep - מיקרו־שניות במספר שלם

  • POSIX::pause - חוסם עד שאות כלשהו מגיע