flock#
Τοποθετεί συμβουλευτικό κλείδωμα σε ένα ανοιχτό αρχείο.
Η flock είναι η φορητή πρωτογενής λειτουργία κλειδώματος αρχείων της Perl. Καλεί τη υποκείμενη flock(2), fcntl(2) ή lockf(3) - όποια παρέχει η πλατφόρμα - στο FILEHANDLE και μπλοκάρει εξ ορισμού μέχρι να μπορέσει να χορηγηθεί το ζητούμενο κλείδωμα. Τα κλειδώματα καλύπτουν ολόκληρο το αρχείο, ποτέ ένα εύρος bytes, και είναι συμβουλευτικά: συντονίζουν μόνο μεταξύ διεργασιών που επίσης καλούν flock στο ίδιο αρχείο. Κώδικας που αγνοεί το κλείδωμα μπορεί ακόμα να διαβάσει ή να τροποποιήσει το περιεχόμενο.
Σύνοψη#
flock FILEHANDLE, OPERATION
Τι επιστρέφεται#
Αληθής τιμή σε επιτυχία, ψευδής τιμή σε αποτυχία (με την $! ορισμένη). Ελέγχετε πάντα την τιμή επιστροφής - με LOCK_NB η αποτυχία είναι το κανονικό σήμα «κάποιος άλλος το κρατά», όχι σφάλμα:
flock($fh, LOCK_EX | LOCK_NB)
or die "already locked: $!";
Σε πλατφόρμα που δεν υλοποιεί κανένα από τα flock(2), κλείδωμα fcntl(2) ή lockf(3), η flock εγείρει μοιραίο σφάλμα αντί να επιστρέψει ψευδή τιμή. Στο Linux (τη μόνη υποστηριζόμενη πλατφόρμα της pperl) αυτό δεν συμβαίνει ποτέ.
Τιμές της OPERATION#
Η OPERATION είναι ένας από τους αμοιβαία αποκλειόμενους τύπους αιτήματος, προαιρετικά συνδυασμένος με δυαδικό OR με τη σημαία μη μπλοκαρίσματος. Οι παραδοσιακές αριθμητικές τιμές είναι 1, 2, 4, 8 αλλά ο φορητός κώδικας εισάγει τα συμβολικά ονόματα από το Fcntl, είτε ξεχωριστά είτε ως ομάδα μέσω της ετικέτας :flock:
use Fcntl qw(:flock);
LOCK_SH- κοινόχρηστο κλείδωμα. Πολλαπλές διεργασίες μπορούν να κρατούν κοινόχρηστο κλείδωμα στο ίδιο αρχείο ταυτόχρονα. Χρησιμοποιείται για αναγνώστες.LOCK_EX- αποκλειστικό κλείδωμα. Μόνο μία διεργασία μπορεί να το κρατά· καμία άλλη διεργασία δεν μπορεί να κρατά κανένα κλείδωμα στο αρχείο ταυτόχρονα. Χρησιμοποιείται για εγγραφείς.LOCK_UN- απελευθερώνει όποιο κλείδωμα κρατά αυτή τη στιγμή αυτό το filehandle.LOCK_NB- δυαδικό OR μεLOCK_SHήLOCK_EXγια να γίνει η κλήση μη μπλοκαριστική· ηflockεπιστρέφει ψευδή τιμή αμέσως αν το κλείδωμα δεν μπορεί να χορηγηθεί, αντί να περιμένει.
Μια κλήση flock με νέα κατάσταση αντικαθιστά ατομικά υπάρχον κλείδωμα στο ίδιο filehandle (για παράδειγμα, αναβάθμιση από LOCK_SH σε LOCK_EX).
Καθολική κατάσταση που επηρεάζει#
Ορίζει την
$!σε αποτυχία.Εκκενώνει τον ενταμιευτή εξόδου του
FILEHANDLEπριν το κλείδωμα ή το ξεκλείδωμα, ώστε τα δεδομένα της κλειδωμένης περιοχής να φτάσουν στο OS πριν μια άλλη διεργασία δει την αλλαγή κατάστασης κλειδώματος.
Παραδείγματα#
Αποκλειστικό κλείδωμα για εγγραφέα, με μπλοκάρισμα μέχρι να χορηγηθεί:
use Fcntl qw(:flock);
open my $fh, ">>", "counter.log" or die $!;
flock($fh, LOCK_EX) or die "lock failed: $!";
print $fh "tick\n";
flock($fh, LOCK_UN) or die "unlock failed: $!";
close $fh;
Μη μπλοκαριστική προσπάθεια - παράλειψη της εργασίας αν τρέχει ήδη άλλη διεργασία:
use Fcntl qw(:flock);
open my $fh, ">", "/var/run/myjob.lock" or die $!;
flock($fh, LOCK_EX | LOCK_NB)
or do { warn "another instance running\n"; exit 0 };
# ... work ...
# lock auto-released when $fh is closed / program exits
Κλασικός appender mailbox. Παρατηρήστε την seek στο SEEK_END μετά το κλείδωμα - σε πολύ παλιά συστήματα η κατάσταση προσθήκης >> δεν είναι ατομική, οπότε η θέση εγγραφής πρέπει να επανακαθιερωθεί μόλις κρατηθεί το κλείδωμα:
use Fcntl qw(:flock SEEK_END);
sub lock_mbox { flock($_[0], LOCK_EX) or die "lock: $!" }
sub unlock_mbox { flock($_[0], LOCK_UN) or die "unlock: $!" }
open my $mbox, ">>", "/var/mail/$ENV{USER}" or die $!;
lock_mbox($mbox);
seek($mbox, 0, SEEK_END) or die "seek: $!";
print $mbox $msg, "\n\n";
unlock_mbox($mbox);
close $mbox;
Κοινόχρηστο κλείδωμα ανάγνωσης κατά τη φόρτωση αρχείου ρυθμίσεων, επιτρέποντας σε άλλους αναγνώστες να προχωρούν ταυτόχρονα:
use Fcntl qw(:flock);
open my $fh, "<", "config.dat" or die $!;
flock($fh, LOCK_SH) or die "lock: $!";
my @lines = <$fh>;
close $fh; # releases the lock
Αναβάθμιση κοινόχρηστου κλειδώματος σε αποκλειστικό - η δεύτερη flock εναλλάσσει ατομικά τις καταστάσεις:
flock($fh, LOCK_SH) or die $!;
# ... inspect contents ...
flock($fh, LOCK_EX) or die $!; # now we intend to write
Οριακές περιπτώσεις#
Τα κλειδώματα είναι ανά filehandle, όχι ανά αρχείο. Δύο ανεξάρτητα ανοίγματα της ίδιας διαδρομής έχουν το καθένα τη δική του θέση κλειδώματος. Γι” αυτό το κλείδωμα του ίδιου του αρχείου σας δύο φορές από την ίδια διεργασία μέσω διαφορετικών handles μπορεί να οδηγήσει σε αδιέξοδο ή να συμπεριφερθεί απρόσμενα σε συστήματα βασισμένα σε
fcntl(2).Το κλείσιμο του filehandle απελευθερώνει το κλείδωμα. Δεν απαιτείται ξεχωριστό βήμα «ξεκλειδώματος» κατά την έξοδο του προγράμματος· η
LOCK_UNείναι χρήσιμη μόνο όταν θέλετε να κρατήσετε το handle ανοιχτό μετά.Η αποτυχία
LOCK_NBδεν είναι croak. Επιστρέφει ψευδή τιμή και θέτει την$!σεEWOULDBLOCK. Αντιμετωπίστε το ως αναμενόμενο αποτέλεσμα, όχι ως σφάλμα.Μόνο συμβουλευτικά. Μια διεργασία που δεν καλεί ποτέ
flockδεν βλέπει κανένα κλείδωμα. Χρησιμοποιήστε τηνflockως πρωτόκολλο συνεργασίας μεταξύ των δικών σας προγραμμάτων, όχι ως μηχανισμό ασφαλείας.Μόνο ολόκληρα αρχεία. Δεν υπάρχει κλείδωμα εύρους bytes μέσω της
flock. Για κλείδωμα σε επίπεδο εγγραφής χρησιμοποιήστεfcntlμεF_SETLK/F_SETLKW.NFS και άλλα δικτυακά συστήματα αρχείων. Ορισμένες παλιότερες υλοποιήσεις NFS δεν μπορούν να τιμήσουν την
flockανάμεσα σε υπολογιστές· η κλήση μπορεί σιωπηρά να γίνει no-op ή να επιστρέψει επιτυχία χωρίς να παρέχει αποκλεισμό. Χρησιμοποιήστε κλείδωμα μέσωfcntlαν ο δικτυακός συντονισμός έχει σημασία.Κληρονομικότητα στο fork. Όταν η πλατφόρμα χρησιμοποιεί πραγματική
flock(2)(όπως το Linux), τα κλειδώματα κληρονομούνται μέσω τουfork· το παιδί τα μοιράζεται με τον γονέα. Σε πλατφόρμες που εξομοιώνουν μέσωfcntl(2)τα κλειδώματα δεν επιβιώνουν του fork, πράγμα που κάνει τη συγγραφή διακομιστών κλειδώματος αρκετά πιο δύσκολη.Εκκένωση ενταμιευτή. Η Perl εκκενώνει τον ενταμιευτή εξόδου του
FILEHANDLEσε κάθε κλήσηflock. Κώδικας που συνδυάζει ενταμιευμένηprintμε κλείδωμα δεν χρειάζεται ρητή εκκένωση πριν το όριο του κλειδώματος.Αλληλεπίδραση με ανοίγματα τύπου
dup. Ένα άνοιγμα της μορφήςopen(my $A, ">>&=", $B)μοιράζεται τον υποκείμενο περιγραφέα αρχείου με το$B, οπότε οιflock($A)καιflock($B)ενεργούν στην ίδια θέση κλειδώματος. Ένα dup>>&δίνει σε κάθε handle τον δικό του περιγραφέα και τη δική του θέση κλειδώματος.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42. Η pperl τρέχει μόνο σε Linux, όπου η flock(2) είναι πάντα διαθέσιμη, οπότε η διαδρομή «η πλατφόρμα δεν διαθέτει πρωτογενή λειτουργία κλειδώματος - μοιραίο σφάλμα» που τεκμηριώνεται upstream δεν ενεργοποιείται ποτέ στην πράξη.
Δείτε επίσης#
fcntl- κλείδωμα εύρους bytes και συμβουλευτικό κλείδωμα με λεπτότερο έλεγχο· χρησιμοποιήστε την όταν η κοκκιδοποίηση σε επίπεδο ολόκληρου αρχείου είναι υπερβολικά αδρή ή όταν το απαιτούν δικτυακά συστήματα αρχείωνopen- παράγει το filehandle στο οποίο λειτουργεί ηflock· να θυμάστε ότι η απαιτούμενη κατάσταση ανοίγματος (<έναντι>) έχει σημασία για τιςLOCK_SH/LOCK_EXπου εξομοιώνονται μέσωfcntlclose- απελευθερώνει οποιοδήποτεflockεξακολουθεί να κρατείται στο handleseek- συνδυάστε μεflockόταν προσθέτετε σε αρχεία που άλλες διεργασίες ενδέχεται να επέκτειναν ενώ περιμένατε για το κλείδωμαfork- η κληρονομικότητα κλειδωμάτων σε διεργασίες-παιδιά εξαρτάται από την υποκείμενη πρωτογενή λειτουργία κλειδώματοςFcntl- πηγή των σταθερώνLOCK_SH,LOCK_EX,LOCK_UN,LOCK_NBκαι της ετικέτας εισαγωγής:flock