Filehandles, αρχεία, κατάλογοι

fcntl#

Εκτελεί μια λειτουργία ελέγχου αρχείου fcntl(2) σε ένα filehandle.

Η fcntl είναι η άμεση σύνδεση της Perl με την κλήση συστήματος POSIX fcntl(2). Διαβάζει ή αλλάζει κατάσταση ανά περιγραφέα - μη μπλοκαριστική λειτουργία, close-on-exec, συμβουλευτικά κλειδώματα εγγραφών, σημαίες περιγραφέα - επικαλούμενη τη FUNCTION επί του FILEHANDLE, με το SCALAR να παίζει ρόλο είτε ως όρισμα εισόδου, είτε ως ενταμιευτής εξόδου, είτε και τα δύο, ανάλογα με τη FUNCTION που περνάτε.

Οι κωδικοί FUNCTION δεν είναι κυριολεκτικά σε επίπεδο Perl· είναι μακροεντολές του προεπεξεργαστή C που εκτίθενται από το άρθρωμα Fcntl. Φορτώστε το πρώτα, αλλιώς η FUNCTION θα είναι ένα αόριστο bareword:

use Fcntl;

Σύνοψη#

use Fcntl;
fcntl FILEHANDLE, FUNCTION, SCALAR
my $flags = fcntl($fh, F_GETFL, 0);
fcntl($fh, F_SETFL, $flags | O_NONBLOCK);

Τι επιστρέφεται#

Σε επιτυχία, τον ακέραιο που επέστρεψε ο πυρήνας. Όταν αυτός ο ακέραιος είναι 0, η Perl τον αντικαθιστά με τη συμβολοσειρά διπλής τιμής "0 but true" - αληθής σε λογικό περιβάλλον, αριθμητικό 0 σε αριθμητικό περιβάλλον, και εξαιρείται από την προειδοποίηση Argument "..." isn't numeric. Αυτό σας επιτρέπει να ελέγξετε το αποτέλεσμα με or die ακόμα και για λειτουργίες των οποίων η τιμή επιτυχίας είναι κυριολεκτικά μηδέν:

fcntl($fh, F_SETFD, FD_CLOEXEC)
    or die "F_SETFD: $!";

Σε αποτυχία, η fcntl επιστρέφει undef και θέτει το $! στο σχετικό errno. Δεν χρειάζεται να περιτυλίξετε την επιστροφή σε defined - η σύμβαση "0 but true" καθιστά επαρκή έναν απλό έλεγχο αλήθειας.

Για κωδικούς FUNCTION που γράφουν πίσω μέσω του SCALAR (όπως ο F_GETLK), τα ενημερωμένα bytes εμφανίζονται στο βαθμωτό που περάσατε· η επιστρεφόμενη τιμή ακολουθεί παρ” όλα αυτά τον κανόνα παραπάνω.

Πώς χρησιμοποιείται το SCALAR#

Το SCALAR παίζει τρεις διαφορετικούς ρόλους ανάλογα με τη FUNCTION:

  • Ακέραιος εισόδου. Για κλήσεις ρύθμισης σημαιών όπως οι F_SETFD ή F_SETFL, το SCALAR είναι η ακέραια μάσκα bits που θα εγκατασταθεί.

  • Παραβλεπόμενος placeholder. Για κλήσεις ανάγνωσης σημαιών όπως οι F_GETFD ή F_GETFL, το SCALAR δεν χρησιμοποιείται από τον πυρήνα· περάστε 0 συμβατικά.

  • Ενταμιευτής δομής εισόδου/εξόδου. Για κλήσεις κλειδώματος εγγραφών όπως οι F_GETLK, F_SETLK και F_SETLKW, το SCALAR πρέπει να περιέχει μια πακεταρισμένη struct flock - δημιουργήστε την με pack πριν την κλήση, και για την F_GETLK αποκωδικοποιήστε τα επιστρεφόμενα bytes με unpack στη συνέχεια.

Όταν το SCALAR χρησιμοποιείται ως ενταμιευτής εξόδου, προδιαστασιολογήστε το τουλάχιστον στο μήκος της δομής που θα γράψει ο πυρήνας· ένα υπομέγεθες βαθμωτό μεγαλώνει αυτόματα, αλλά η προδιαστασιολόγηση κάνει την πρόθεση εμφανή.

Καθολική κατάσταση που επηρεάζει#

  • $! - τίθεται σε αποτυχία στο errno από την fcntl(2).

  • Οι σημαίες σε επίπεδο περιγραφέα επί του FILEHANDLE (π.χ. O_NONBLOCK, FD_CLOEXEC) διατηρούνται για όλη τη διάρκεια ζωής του περιγραφέα, επιβιώνουν της dup και της fork σύμφωνα με τους κανόνες POSIX, και δεν είναι ορατές από την Perl μέσω κάποιας άλλης μεταβλητής. Ο μόνος τρόπος να τις διαβάσετε πίσω είναι μια άλλη κλήση fcntl με F_GETFL / F_GETFD.

Παραδείγματα#

Κάντε μια υποδοχή μη μπλοκαριστική - η κανονική χρήση:

use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $flags = fcntl($remote, F_GETFL, 0)
    or die "F_GETFL: $!";
fcntl($remote, F_SETFL, $flags | O_NONBLOCK)
    or die "F_SETFL: $!";

Θέστε close-on-exec ώστε ο περιγραφέας να μην κληρονομείται από διεργασίες-παιδιά μέσω exec:

use Fcntl qw(F_SETFD FD_CLOEXEC);

fcntl($fh, F_SETFD, FD_CLOEXEC)
    or die "F_SETFD: $!";

Διαβάστε τις τρέχουσες σημαίες περιγραφέα και ελέγξτε ένα bit:

use Fcntl qw(F_GETFD FD_CLOEXEC);

my $fd_flags = fcntl($fh, F_GETFD, 0);
defined $fd_flags or die "F_GETFD: $!";
if ($fd_flags & FD_CLOEXEC) {
    # descriptor will close on exec
}

Τοποθετήστε ένα συμβουλευτικό κλείδωμα εγγραφής σε ολόκληρο το αρχείο. Η διάταξη της struct flock είναι ειδική της πλατφόρμας· σε Linux το s s l l i καλύπτει τα l_type l_whence l_start l_len l_pid:

use Fcntl qw(F_SETLK F_WRLCK SEEK_SET);

my $lock = pack('s s l l i', F_WRLCK, SEEK_SET, 0, 0, 0);
fcntl($fh, F_SETLK, $lock)
    or die "lock refused: $!";

Απενεργοποίηση μιας μεμονωμένης σημαίας - μασκάρετε εκτός το O_NONBLOCK για να επαναφέρετε ένα handle σε μπλοκαριστική λειτουργία:

use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $flags = fcntl($fh, F_GETFL, 0);
fcntl($fh, F_SETFL, $flags & ~O_NONBLOCK)
    or die "F_SETFL: $!";

Οριακές περιπτώσεις#

  • Ξεχάστηκε το use Fcntl: τα F_GETFL και συναφή αναλύονται ως barewords και αποτιμώνται σε ενόχληση επιπέδου προειδοποίησης υπό use strict / use warnings, ή στη συμβολοσειρά "F_GETFL" διαφορετικά - και στις δύο περιπτώσεις η κλήση αποτυγχάνει με EINVAL. Φορτώνετε πάντα πρώτα το Fcntl.

  • Επιστροφή "0 but true": μη συγκρίνετε την επιστροφή με == 0 ως δοκιμή αποτυχίας. Χρησιμοποιήστε απλό λογικό (or die) ή defined - το πρώτο αποτελεί το ιδίωμα.

  • F_SETLK έναντι F_SETLKW: η F_SETLK επιστρέφει undef και θέτει το $! σε EAGAIN / EACCES όταν άλλη διεργασία κρατά ένα κλείδωμα που συγκρούεται. Η F_SETLKW μπλοκάρει μέχρι να εκχωρηθεί το κλείδωμα. Επιλέξτε σκόπιμα· η σύγχυσή τους είναι η συνηθισμένη πηγή κρεμασμάτων.

  • Έξοδος της F_GETLK: σε επιτυχία τα bytes της struct flock στο SCALAR γράφονται από πάνω με πληροφορίες για το συγκρουόμενο κλείδωμα (ή l_type == F_UNLCK αν η περιοχή είναι ελεύθερη). Κάντε unpack με το ίδιο πρότυπο με το οποίο πακετάρατε.

  • Δεν υλοποιεί κάθε σύστημα κάθε FUNCTION: η fcntl εγείρει εξαίρεση σε μηχάνημα που δεν υλοποιεί καθόλου την fcntl(2). Σε συστήματα που την υλοποιούν, μη υποστηριζόμενοι κωδικοί FUNCTION αποτυγχάνουν με EINVAL μέσω του $!. Το άρθρωμα Fcntl εξάγει μόνο τις σταθερές που η τρέχουσα πλατφόρμα πράγματι ορίζει.

  • fcntl έναντι ioctl: μοιράζονται τη σύμβαση επεξεργασίας ορισμάτων και τιμής επιστροφής, αλλά στοχεύουν διαφορετικές διεπαφές πυρήνα. Χρησιμοποιήστε την fcntl για σημαίες περιγραφέα και συμβουλευτικά κλειδώματα· χρησιμοποιήστε την ioctl για κωδικούς ελέγχου ειδικούς ανά συσκευή.

  • fcntl έναντι flock: η flock χρησιμοποιεί κλειδώματα ολόκληρου αρχείου τύπου BSD flock(2), τα οποία σε Linux συνεργάζονται με τα POSIX κλειδώματα της fcntl μόνο με περιορισμένους τρόπους. Αν χρειάζεστε κλείδωμα εύρους bytes ή σημασιολογία POSIX (κλείδωμα που απελευθερώνεται σε οποιοδήποτε close του αρχείου από τη διεργασία κατόχου), χρησιμοποιήστε την fcntl με F_SETLK· διαφορετικά η flock είναι απλούστερη.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • Fcntl - το άρθρωμα που εξάγει τις σταθερές F_* / O_* / FD_* / SEEK_* που αναμένει η fcntl· κάντε πάντα use πρώτα

  • ioctl - ίδια σύμβαση κλήσης και τιμής επιστροφής με την fcntl, αλλά για κωδικούς ελέγχου συσκευών αντί για σημαίες ελέγχου αρχείου

  • flock - απλούστερα συμβουλευτικά κλειδώματα ολόκληρου αρχείου· επιλέξτε την όταν δεν χρειάζεστε εύρος bytes ή σημασιολογία POSIX

  • open - ανοίγει εξαρχής το filehandle· ορισμένες σημαίες που ρυθμίζει η fcntl (π.χ. O_NONBLOCK, O_APPEND) μπορούν επίσης να τεθούν κατά το άνοιγμα

  • sysopen - χαμηλού επιπέδου άνοιγμα που δέχεται τις ίδιες σημαίες O_* από το Fcntl· χρησιμοποιήστε το όταν θέλετε οι σημαίες να εφαρμοστούν ατομικά αντί μέσω μιας επακόλουθης fcntl(F_SETFL)

  • pack / unpack - απαιτούνται για την κατασκευή και αποκωδικοποίηση του ενταμιευτή struct flock που χρησιμοποιείται από τις F_GETLK / F_SETLK