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χρησιμοποιεί κλειδώματα ολόκληρου αρχείου τύπου BSDflock(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 ή σημασιολογία POSIXopen- ανοίγει εξαρχής το filehandle· ορισμένες σημαίες που ρυθμίζει ηfcntl(π.χ.O_NONBLOCK,O_APPEND) μπορούν επίσης να τεθούν κατά το άνοιγμαsysopen- χαμηλού επιπέδου άνοιγμα που δέχεται τις ίδιες σημαίεςO_*από τοFcntl· χρησιμοποιήστε το όταν θέλετε οι σημαίες να εφαρμοστούν ατομικά αντί μέσω μιας επακόλουθηςfcntl(F_SETFL)pack/unpack- απαιτούνται για την κατασκευή και αποκωδικοποίηση του ενταμιευτήstruct flockπου χρησιμοποιείται από τιςF_GETLK/F_SETLK