קלט/פלט

fileno#

מחזיר את מספר ה־file descriptor ברמת מערכת ההפעלה מאחורי מטפל קובץ.

fileno מסתכל מעבר להפשטה של מטפל הקובץ המאוגר של Perl ונותן לך את ה־descriptor השלם הגולמי שהקרנל משתמש בו. הוא הגשר בין I/O של Perl לקריאות מערכת שמדברות descriptors ישירות - select, POSIX::dup2, fcntl, או כל דבר ב־IO::Poll / IO::Select. על מטפל ספרייה הוא שואל את אותה שאלה כנגד dirfd(3), שלא כל פלטפורמה מספקת.

תקציר#

fileno FILEHANDLE
fileno DIRHANDLE
fileno EXPR            # EXPR evaluated as an indirect handle

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

  • מספר שלם >= 0 - ה־file descriptor של מערכת ההפעלה - עבור מטפל פתוח רגיל המגובה באובייקט קרנל אמיתי.

  • -1 כאשר המטפל פתוח אך אין לו descriptor אמיתי. זה מה שאתה מקבל עבור מטפלי in-memory שנוצרו על־ידי open עם הפניית סקלר כארגומנט שלישי (open my $fh, ">", \$buf).

  • undef כאשר המטפל סגור, מעולם לא נפתח, או - על מטפל ספרייה - כאשר הפלטפורמה חסרה את dirfd(3). במקרה של מטפל ספרייה $! נקבע.

שלוש מחלקות ההחזרה חשובות. קוד שבודק fileno($fh) עבור אמת מערבב בין ״אין fd כזה״ ל־״fd מספר 0״ (STDIN). השווה תמיד במפורש:

my $fd = fileno $fh;
die "handle not open"      unless defined $fd;
die "handle has no real fd" if $fd == -1;

מצב גלובלי שהוא נוגע בו#

  • $! - נקבע כאשר fileno על מטפל ספרייה נכשל כי לפלטפורמה אין מקבילה ל־dirfd(3).

fileno אינו קורא או כותב לאף גלובל I/O אחר. הוא לא עושה flush, לא מבצע seek, ולא משנה את המטפל הנבחר כעת.

דוגמאות#

המקרה הנפוץ - הפוך מטפל קובץ של Perl למספר fd שקריאת מערכת רוצה:

open my $fh, "<", "/etc/hostname" or die $!;
print fileno $fh, "\n";             # e.g. "3"

למטפלים סטנדרטיים תמיד יש descriptors קבועים 0, 1, 2:

print fileno STDIN,  "\n";          # 0
print fileno STDOUT, "\n";          # 1
print fileno STDERR, "\n";          # 2

בדוק האם שני מטפלים הם כפילים של אותו descriptor שמתחת (האידיום מ־POD של upstream, מותאם למקרה של -1):

if (fileno($this) != -1 && fileno($this) == fileno($that)) {
    print "\$this and \$that are dups\n";
} elsif (fileno($this) != -1 && fileno($that) != -1) {
    print "\$this and \$that have different "
        . "underlying file descriptors\n";
} else {
    print "at least one handle has no real file descriptor\n";
}

למטפלי in-memory אין אובייקט קרנל, כך ש־fileno מחזיר -1:

my $buf = "";
open my $mh, ">", \$buf or die $!;
print fileno $mh, "\n";             # -1

בנה bitmap של descriptor עבור select - השימוש מספר הלימוד עבור fileno:

my $rin = "";
vec($rin, fileno($sock),  1) = 1;
vec($rin, fileno(STDIN),  1) = 1;
my $n = select(my $rout = $rin, undef, undef, 5.0);

מטפלי ספרייה, היכן שהפלטפורמה תומכת ב־dirfd(3):

opendir my $dh, "." or die $!;
my $dfd = fileno $dh;
if (defined $dfd) {
    # use with fstat, openat, fchdir, ...
} else {
    warn "no dirfd on this platform: $!";
}

מקרי קצה#

  • מטפל סגור: מחזיר undef. אין אזהרה תחת use warnings - fileno שקט בכוונה כך שניתן להשתמש בו כבדיקה.

  • bareword שמעולם לא נפתח: fileno NOSUCH מחזיר undef; מצב strict יסרב ל־bareword בזמן הידור אלא אם הוא מוצהר.

  • מטפלי סקלר in-memory: מחזירים -1, לא undef. התייחסות ל־-1 כ־״פתוח אך לא־שמיש לקריאות מערכת״ היא החוזה המיועד - המטפל עצמו עדיין עובד עבור print, readline, וכו«.

  • מלכודת fileno(-1): if (fileno $fh) { ... } מפורש הוא באג שמחכה לקרות: fd 0 הוא STDIN. השתמש ב־defined והשווה כנגד -1 במפורש.

  • מטפל קובץ עקיף דרך ביטוי: אם FILEHANDLE הוא ביטוי כלשהו מלבד bareword או סקלר פשוט, ערכו נלקח כ־שם מטפל עקיף (מחרוזת), לא כאובייקט מטפל. כדי להעביר מטפל המוחזק במבנה נתונים, בצע dereference קודם:

    fileno $handles[0];                 # indirect: uses the string
    fileno ${ \$handles[0] };           # still wrong
    fileno $handles[0]->fileno;         # wrong: calling a method on ""
    my $fh = $handles[0]; fileno $fh;   # right
    
  • מטפל ספרייה בפלטפורמות ללא dirfd(3): מחזיר undef וקובע $!. ללינוקס יש dirfd(3), כך שביעדים הנתמכים של pperl מסלול זה אינו מופעל.

  • מטפלים קשורים: fileno קורא למתודת FILENO של מחלקת ה־tie אם מוגדרת; אחרת מחזיר undef. המחלקה הקשורה אחראית להחזיר ערך הגיוני (-1 עבור ״אין fd״ הוא המוסכמה).

  • מטפלים מ־dup: שני מטפלים שנפתחו עם open מאותו fd שמתחת (למשל open my $copy, ">&", $orig) מחזירים את ה־descriptor החדש, לא את המקורי - ה־dup יצר fd חדש.

הבדלים מ־upstream#

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

ראו גם#

  • open - יוצר את מטפלי הקבצים ש־fileno בוחן; המצבים >& ו־<&= לוקחים מספרי descriptor שעוברים נסיעה חזור דרך fileno

  • opendir - מקור של מטפלי ספרייה עבור צורת מטפל הספרייה של fileno

  • close - שלאחריו fileno על אותו מטפל מחזיר undef

  • select - הצורה בת ארבעת הארגומנטים צורכת bitmaps שנבנו מערכי fileno

  • binmode - עובד על שכבת PerlIO מעל ל־fd; fileno מגיע אל מתחת אליה