semop#
Εκτελεί ατομικά μία ή περισσότερες λειτουργίες σηματοφόρου System V.
Η semop είναι το άλογο εργασίας στη χρήση σηματοφόρων SysV: παίρνει ένα αναγνωριστικό συνόλου σηματοφόρων (από την semget) και μια πακεταρισμένη λίστα λειτουργιών, και κατόπιν ζητά από τον πυρήνα να τις εφαρμόσει όλες ή καμία. Κάθε λειτουργία ονομάζει έναν μεμονωμένο σηματοφόρο μέσα στο σύνολο, ένα ποσό προς πρόσθεση σε αυτόν (συνήθως -1 για αναμονή, +1 για σήμα) και μια λέξη σημαιών. Ο πυρήνας μπλοκάρει τον καλούντα μέχρι κάθε ζητούμενη λειτουργία να μπορεί να προχωρήσει, και κατόπιν τις δεσμεύει ως μία μονάδα. Αυτό κάνει την semop αξιοποιήσιμη ως πρωτογενή λειτουργία αμοιβαίου αποκλεισμού ή μέτρησης πόρων μεταξύ άσχετων διεργασιών.
Σύνοψη#
semop $semid, $opstring
Τι επιστρέφεται#
Αληθής τιμή σε επιτυχία, ψευδής τιμή σε σφάλμα με την $! ορισμένη. Η τιμή αλήθειας είναι το μόνο αποτέλεσμα - η semop επικοινωνεί το αποτέλεσμα μέσω της παρενέργειας στο σύνολο σηματοφόρων, όχι μέσω της επιστροφής της. Ελέγξτε την σε κάθε κλήση:
semop($semid, $ops)
or die "semop failed: $!";
Η ψευδής επιστροφή σημαίνει ότι καμία λειτουργία στην OPSTRING δεν εφαρμόστηκε· η σημασιολογία SysV εγγυάται όλα-ή-τίποτα.
Καθολική κατάσταση που επηρεάζει#
Ορίζει την $! σε αποτυχία, με τις συνήθεις τιμές errno από την semop(2): EAGAIN όταν είχε οριστεί το IPC_NOWAIT και η λειτουργία θα μπλοκάριζε, EIDRM όταν το σύνολο σηματοφόρων αφαιρέθηκε ενώ περίμενε, EINTR όταν σήμα διέκοψε την αναμονή, EINVAL για κακό αριθμό ή αναγνωριστικό σηματοφόρου, EACCES για αναντιστοιχία δικαιωμάτων έναντι του mode του συνόλου.
Η δομή της λειτουργίας#
Η OPSTRING είναι συνένωση εγγραφών σταθερού πλάτους. Κάθε εγγραφή είναι τρεις ακέραιοι short σε εγγενές πλάτος και παράγεται με pack:
pack("s!3", $semnum, $semop, $semflag)
$semnum- ο δείκτης του σηματοφόρου-στόχου μέσα στο σύνολο (0έωςnsems-1, όπου τοnsemsείναι το μέγεθος που πέρασε στηνsemget).$semop- το ποσό που προστίθεται στην τιμή του σηματοφόρου. Οι αρνητικές τιμές περιμένουν μέχρι ο σηματοφόρος να είναι τουλάχιστον|$semop|πριν αφαιρέσουν· οι θετικές τιμές προσθέτουν χωρίς συνθήκη και ξυπνούν όσους περιμένουν· το μηδέν περιμένει μέχρι ο σηματοφόρος να φτάσει το μηδέν.$semflag- δυαδικό OR τουIPC_NOWAIT(αποτυγχάνει μεEAGAINαντί να μπλοκάρει) και τουSEM_UNDO(ζητά από τον πυρήνα να αναιρέσει τη λειτουργία αν η διεργασία τερματίσει χωρίς να την αναιρέσει - απαραίτητο για χρήσεις τύπου κλειδώματος όπου ένα crash δεν πρέπει να αφήσει τον σηματοφόρο κρατημένο).
Το μήκος της OPSTRING υπονοεί τον αριθμό των λειτουργιών: ο πυρήνας επεξεργάζεται length($opstring) / sizeof(struct sembuf) εγγραφές. Το πέρασμα δύο εγγραφών πακεταρισμένων αλληλένδετα ζητά δύο λειτουργίες που εφαρμόζονται ατομικά.
Το s! στο πρότυπο είναι ο εγγενής short, που ταιριάζει στη διάταξη του sembuf στο Linux. Το σκέτο s είναι 16-bit προσημασμένο σε network-order και θα κάνει σιωπηρά λανθασμένο πακετάρισμα σε οποιαδήποτε πλατφόρμα όπου sizeof(short) != 2 ή όπου η endianness διαφέρει από το network order.
Παραδείγματα#
Αναμονή στον (μείωση κατά 1) σηματοφόρο 0 του συνόλου στο $semid:
my $op = pack("s!3", 0, -1, 0);
semop($semid, $op)
or die "wait on semaphore failed: $!";
Σήμα (αύξηση κατά 1) στον ίδιο σηματοφόρο:
my $op = pack("s!3", 0, 1, 0);
semop($semid, $op)
or die "signal failed: $!";
Προσπάθεια απόκτησης χωρίς μπλοκάρισμα - αποτυχία γρήγορα αν τον κρατά κάποιος άλλος:
use POSIX qw(EAGAIN);
my $op = pack("s!3", 0, -1, IPC_NOWAIT);
unless (semop($semid, $op)) {
die "semop: $!" unless $! == EAGAIN;
# contended; caller decides what to do
}
Απόκτηση του σηματοφόρου 0 με αυτόματη απελευθέρωση στην έξοδο της διεργασίας - το μοτίβο για αμοιβαίο αποκλεισμό ασφαλή σε crash:
my $op = pack("s!3", 0, -1, SEM_UNDO);
semop($semid, $op) or die "lock: $!";
# critical section
my $release = pack("s!3", 0, 1, SEM_UNDO);
semop($semid, $release) or die "unlock: $!";
Δύο λειτουργίες που εφαρμόζονται ατομικά - αναμονή στους σηματοφόρους 0 και 1 μαζί, χωρίς να απελευθερωθεί κανείς αν κάποιος από τους δύο θα μπλόκαρε:
my $ops = pack("s!3", 0, -1, 0)
. pack("s!3", 1, -1, 0);
semop($semid, $ops) or die "paired wait: $!";
Αναμονή να φτάσει στο μηδέν ο σηματοφόρος 0 - η μορφή «φράγμα», όπου το $semop είναι μηδέν αντί για αρνητικό:
my $op = pack("s!3", 0, 0, 0);
semop($semid, $op) or die "barrier: $!";
Οριακές περιπτώσεις#
Σύντομη
OPSTRING: το μήκος πρέπει να είναι ακριβές πολλαπλάσιο του μεγέθους εγγραφήςsembuf. Συμβολοσειρά αποκομμένη ή με padding δίνειEINVAL. Χτίζετε πάντα τη συμβολοσειρά από κλήσειςpack, ποτέ στο χέρι.Το εγγενές πλάτος έχει σημασία:
s!3και όχιs3. Ένα σενάριο γραμμένο με σκέτοsλειτουργεί σε υπολογιστή με 16-bit short κατά τύχη και σπάει αλλού.Μηδενικού μήκους
OPSTRING: ζητά μηδέν λειτουργίες. Ο πυρήνας το αποδέχεται και επιστρέφει επιτυχία χωρίς παρενέργειες - σπάνια αυτό που θέλετε. Προστατέψτε την κλήση μεreturn unless length $ops.Διακοπή από σήμα: μια μπλοκαρισμένη
semopπου επιστρέφει με την$!ορισμένη σεEINTRδεν είναι σφάλμα - επαναλάβετε εκτός αν εγκαταστήσατε χειριστή που θέλει να ματαιώσει. Ο προεπιλεγμένος χειρισμός$SIG{*}της Perl δεν επανεκκινεί αυτόματα την κλήση συστήματος.Το
SEM_UNDOμε ζευγαρωμένα ταιριαστά ζεύγη: ο πυρήνας παρακολουθεί τη σωρευτική προσαρμογή ανά σηματοφόρο ανά διεργασία. Η απόκτηση δύο φορές μεSEM_UNDOκαι κατόπιν μία απελευθέρωση αφήνει ένα εκκρεμές-1να αναιρεθεί κατά την έξοδο. Ζευγαρώστε κάθε-1με ένα ταιριαστό+1στην κανονική ροή· τοSEM_UNDOείναι ασφάλεια έναντι crashes, όχι υποκατάστατο της απελευθέρωσης.Αφαιρεμένο σύνολο κατά την αναμονή: αν άλλη διεργασία καλέσει
semctlμεIPC_RMID, κάθε μπλοκαρισμένηsemopεπιστρέφει ψευδή τιμή με την$!ορισμένη σεEIDRM. Το αναγνωριστικό σηματοφόρου είναι άκυρο από εκείνο το σημείο και μετά.Δικαιώματα: η
semopελέγχει το δικαίωμα αλλαγής στο σύνολο. Μια διεργασία που μπορεί να κάνειsemgetένα read-only handle δεν μπορεί παρ” όλα αυτά να εκτελέσειsemopσε αυτό.Μεγάλο πλήθος λειτουργιών: ο πυρήνας περιορίζει τον αριθμό λειτουργιών ανά κλήση στο
SEMOPM(συνήθως 32). Το χτίσιμο μιαςOPSTRINGμε περισσότερες εγγραφές αποτυγχάνει μεE2BIG.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
semget- αποκτήστε το αναγνωριστικό που περνάτε ως πρώτο όρισμα· οι δύο χρησιμοποιούνται πάντα μαζίsemctl- ορίζει ή ερωτά τις τιμές σηματοφόρων, και αφαιρεί το σύνολο όταν τελειώσετε με αυτόpack- χτίζει κάθε εγγραφήsembuf·s!3είναι το πρότυπο που θέλετεmsgsnd- το αντίστοιχο για ουρές μηνυμάτων όταν χρειάζεστε να περάσετε δεδομένα αντί να σηματοδοτήσετε διαθεσιμότηταshmget- το αντίστοιχο για κοινόχρηστη μνήμη· οι σηματοφόροι χρησιμοποιούνται συνήθως για να προστατέψουν την πρόσβαση σε ένα τμήμα κοινόχρηστης μνήμης SysVIPC::SysV- εξάγει τις σταθερέςIPC_NOWAIT,SEM_UNDOκαιIPC_RMIDπου χρησιμοποιούνται στο$semflagκαι στις εντολέςsemctlIPC::Semaphore- αντικειμενοστραφές περιτύλιγμα πάνω από τιςsemget/semop/semctlόταν η διαδικαστική διεπαφή φαντάζει υπερβολικά γυμνή