קלט/פלט · מטפלי קובץ קבצים ספריות
select#
או להגדיר את מטפל הקובץ של פלט ברירת המחדל, או לקרוא ל־syscall select(2) לריבוב I/O. אותו שם, שתי משימות לא־קשורות - מובחנות לפי מספר הארגומנטים.
צורת הארגומנט הבודד (או צורת ללא ארגומנטים) עוסקת בלאן print, printf, say, ו־write שולחים את הפלט שלהם כאשר אין נקיבה במטפל קובץ. צורת ארבעת הארגומנטים היא עטיפה ישירה סביב ה־syscall select(2) של BSD להמתנה על קבוצות של file descriptors.
תקציר#
select FILEHANDLE # set default output handle, return old
select # return current default output handle
select RBITS, WBITS, EBITS, TIMEOUT # select(2) syscall
מה מקבלים בחזרה#
select FILEHANDLE מחזיר את מטפל הקובץ שנבחר קודם (כ־typeglob), כך שתבנית ה־save/restore המקובלת עובדת:
my $old = select $fh;
$| = 1;
select $old;
select (ללא ארגומנטים) מחזיר את מטפל הקובץ הנבחר כעת. בהתחלת התוכנית זהו STDOUT.
select RBITS, WBITS, EBITS, TIMEOUT מחזיר דברים שונים בהקשרים שונים:
בהקשר סקלרי: מספר מטפלי הקובץ המוכנים, או
-1בשגיאה כאשר$!מוגדר.בהקשר רשימה:
($nfound, $timeleft)- אותו$nfoundבתוספת הזמן הנותר מ־TIMEOUT. קרנלים רבים אינם מעדכנים את$timeleft; באותן מערכות הוא תמיד שווה ל־TIMEOUTשל הקלט.
בפקיעת timeout $nfound הוא 0. שלושת מסכות הביט (RBITS, WBITS, EBITS) מתעדכנות במקום כדי לציין אילו descriptors מוכנים - יש להעביר עותקים אם רוצים לשמר את המסכות המקוריות.
מצב גלובלי שהוא נוגע בו#
צורת הארגומנט הבודד משנה פיסת מצב גלובלי אחת של המפרש: מטפל הקובץ של פלט הנבחר כעת. בעוד המטפל הזה נבחר, משתנים אלה מתייחסים אליו, לא ל־STDOUT:
זוהי הסיבה ש־my $old = select($fh); $| = 1; select($old); עובד: $| הוא תכונה של המטפל הנבחר, לא סקלר גלובלי.
צורת ארבעת הארגומנטים אינה נוגעת במצב פר־מפרש. היא עשויה להשאיר את $! מוגדר בשגיאה.
דוגמאות#
להפעיל autoflush על מטפל מבלי להפריע לברירת המחדל:
my $old = select $fh; $| = 1; select $old;
להפנות מחדש את print באופן זמני ולשחזר ביציאת הבלוק:
{
my $old = select $log_fh;
print "entry: $msg\n"; # goes to $log_fh
select $old;
}
לישון 250 מילישניות באמצעות צורת ארבעת הארגומנטים:
select undef, undef, undef, 0.25;
להמתין עד 5 שניות ל־STDIN להפוך לקריא:
my $rin = '';
vec($rin, fileno(STDIN), 1) = 1;
my $nfound = select my $rout = $rin, undef, undef, 5;
if ($nfound) {
my $line = <STDIN>;
}
לבנות מסכת קריאה על מספר מטפלים:
sub fhbits {
my $bits = '';
vec($bits, fileno($_), 1) = 1 for @_;
return $bits;
}
my $rin = fhbits(\*STDIN, $sock);
my ($nfound, $timeleft) =
select my $rout = $rin, undef, undef, 10;
מקרי קצה#
חלופה בסגנון מתודה.
$fh->autoflush(1)מגדיר את דגל ה־autoflush על$fhמבלי לשנות את מטפל ברירת המחדל. עדיף כאשר נדרש רק לעדכן תכונה אחת של מטפל אחד - אין מצב גלובלי מעורב.Localization של typeglob נקייה יותר עבור הפניות מחדש מוגבלות־תחום.
local *STDOUT = $fhקושר מחדש אתSTDOUTעצמו עבור התחום הדינמי; ב־dieהמקורי משוחזר אוטומטית.selectאינו משחזר ב־die. השניים אינם שווי־ערך: עםselectהוראתprint STDOUT ...מפורשת עדיין מגיעה ל־STDOUTהאמיתי; עם צורתlocal *STDOUT, גםprint STDOUT ...הולך למטפל הקשור מחדש.צורת מסכת ביט דורשת בתים, לא רשימה של מספרי fileno שלמים. מסכת ביט היא מחרוזת ביט ארוזה שנבנתה עם
vec; העברת רשימה של מספרים שלמים או הפניה מייצרת בשקט תוצאות שגויות (או מסכה ריקה).undefעבור מסכה משמעו ״לא להמתין על הקבוצה הזו.״ יש להעבירundefעבור מסכות שלא אכפת מהן. מחרוזת ריקה''טכנית גם עובדת אך פחות מקובלת.Timeouts שבריריים עובדים.
TIMEOUTהוא float בשניות.0.25הוא 250 מילישניות;0חוזר מיד (תשאול).TIMEOUTשלundefמשמעו לחסום ללא הגבלה עד שלפחות descriptor אחד מוכן או שאות מגיע.מסכות משונות במקום. בהחזרה, כל מסכה מחזיקה רק את הביטים עבור descriptors שמוכנים. אם נדרשים המקוריים אחר כך, יש להעביר עותקים - המבנה
my $rout = $rinבשורת הקריאה עושה בדיוק את זה.אין לערבב I/O עם buffering עם צורת ארבעת הארגומנטים.
selectמדווח על מוכנות ברמת הקרנל;readline,read, ואופרטור היהלום<>קוראים דרך מאגרי PerlIO שעשויים כבר להחזיק נתונים שלא נקראו שהקרנל אינו יודע עליהם. יש להשתמש ב־sysreadלנתונים ברגע ש־selectאומר שהדסקריפטור מוכן.מוכנות מזויפת על סוקטים. ב־Unixes מסוימים
select(2)עשוי לדווח על סוקט כ־״מוכן לקריאה״ כאשרreadעוקב עדיין יחסום. יש להגדירO_NONBLOCKעל הסוקט אם זה חשוב.התנהגות restart-after-signal תלויה במערכת. אות (לדוגמה
SIGALRM) עשוי לגרום ל־selectלחזור מוקדם עם$! == EINTR, או שהקרנל עשוי להפעיל מחדש את הקריאה בשקיפות. קוד נייד בודקEINTRבמפורש.מספר הארגומנטים מבחין בין שתי הצורות. ארגומנט אחד (או אפס) היא צורת מטפל ברירת המחדל; ארבעה בדיוק היא צורת ה־syscall. ספירות אחרות הן שגיאת תחביר.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
print- קורא את המטפל הנבחר כאשר לא ניתן מטפל קובץ;selectהוא הדרך לשנות איזה מטפל זהprintf- אותו כלל של מטפל ברירת המחדל כמוprintwrite- פלט מבוסס־format; משתני top-of-form ואורך־עמוד עוקבים אחר המטפל הנבחר, לא אחרSTDOUTfileno- ממפה מטפל קובץ למספר descriptor שלם שדרוש בעת בניית מסכהvec- אורז מספרי descriptor לתוך מחרוזת הביט שצורת ארבעת הארגומנטים מצפה להsysread- הקריאה ללא buffering שמשתמשים בה אחרי ש־selectארבע־ארגומנטים אומר שדסקריפטור מוכןIO::Select- עטיפת עצם על צורת ארבעת הארגומנטים שמסתירה את חשבון מסכות הביט