SysV IPC

msgctl#

Εκτελεί μια λειτουργία ελέγχου σε ουρά μηνυμάτων IPC System V.

Η msgctl είναι άμεσο wrapper γύρω από την κλήση συστήματος C msgctl(2). Επιθεωρεί, τροποποιεί ή αφαιρεί την ουρά μηνυμάτων που αναγνωρίζεται από το ID. Η λειτουργία που επιλέγεται από τη CMD καθορίζει πώς χρησιμοποιείται το ARG - είτε ως περιγραφέας εισόδου, είτε ως ενταμιευτής εξόδου, είτε αγνοείται εντελώς. Οι συμβολικές σταθερές που χρειάζονται για τη CMD (IPC_STAT, IPC_SET, IPC_RMID, και σε Linux οι IPC_INFO, MSG_STAT, MSG_INFO) ζουν στο IPC::SysV, το οποίο πρέπει να εισαγάγετε πριν επιλυθούν τα ονόματα.

Σύνοψη#

use IPC::SysV;

msgctl $id, IPC_STAT, $buf       # read queue info into $buf
msgctl $id, IPC_SET,  $buf       # write queue info from $buf
msgctl $id, IPC_RMID, 0          # destroy the queue

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

Η τιμή επιστροφής ακολουθεί την ίδια σύμβαση με την ioctl:

  • undef σε σφάλμα, με το $! τεθειμένο.

  • Τη συμβολοσειρά "0 but true" όταν η υποκείμενη κλήση επέστρεψε 0. Αυτή είναι η περίπτωση επιτυχίας με μηδενική τιμή - δοκιμάζεται ως αληθής σε λογικό περιβάλλον και συγκρίνεται ίση με 0 σε αριθμητικό περιβάλλον, οπότε ένας έλεγχος χειρίζεται τόσο επιτυχία όσο και αποτυχία.

  • Την ακατέργαστη μη μηδενική ακέραια επιστροφή διαφορετικά (για παράδειγμα τον δείκτη που επιστρέφει η ειδική του Linux MSG_STAT).

Η σύμβαση "0 but true" υπάρχει ακριβώς ώστε η msgctl(...) or die να κάνει το σωστό πράγμα ακόμη και όταν η κλήση συστήματος επιστρέφει νόμιμα μηδέν:

msgctl $id, IPC_RMID, 0
    or die "msgctl IPC_RMID failed: $!";

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

Το ARG παίζει τρεις διαφορετικούς ρόλους ανάλογα με τη CMD. Ο πυρήνας αγγίζει τη μνήμη μόνο στις κατευθύνσεις που απαιτεί η εντολή:

  • IPC_STAT - το ARG πρέπει να είναι εγγράψιμο βαθμωτό. Ο πυρήνας το γεμίζει με την πακεταρισμένη δομή msqid_ds που περιγράφει την ουρά (δικαιώματα, ιδιοκτήτη, χρόνους τελευταίας αποστολής/τελευταίας λήψης, όρια bytes ουράς, καταμετρήσεις). Κάντε unpack με βοηθούς του IPC::SysV αντί να γράψετε τη διάταξη χειρωνακτικά· η msqid_ds ποικίλλει μεταξύ πυρήνων και εκδόσεων libc.

  • IPC_SET - το ARG πρέπει να περιέχει πακεταρισμένη msqid_ds που παρήχθη από προηγούμενη IPC_STAT στην ίδια (ή συμβατή) ουρά. Τιμώνται μόνο μερικά πεδία: msg_perm.uid, msg_perm.gid, msg_perm.mode (κατώτερα 9 bits) και msg_qbytes. Τα υπόλοιπα αγνοούνται.

  • IPC_RMID - το ARG δεν χρησιμοποιείται. Περάστε 0. Η ουρά σημειώνεται προς καταστροφή· οποιαδήποτε μπλοκαρισμένη msgsnd / msgrcv σε αυτήν αποτυγχάνει με EIDRM.

Μόνο σε Linux, οι MSG_STAT και MSG_INFO δέχονται επίσης εγγράψιμο βαθμωτό για το ARG και επιστρέφουν επιπλέον δεδομένα· αυτές δεν είναι φορητές και θα πρέπει να φραγούν πίσω από έλεγχο κατά τον χρόνο εκτέλεσης.

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

  • $! - τίθεται σε αποτυχία με το errno του συστήματος (EPERM, EACCES, EINVAL, EIDRM, EFAULT είναι οι συνηθισμένες τιμές).

  • Καμία άλλη ειδική μεταβλητή δεν επηρεάζεται.

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

Διαβάστε την κεφαλίδα της ουράς και επιθεωρήστε το τρέχον όριο bytes:

use IPC::SysV qw(IPC_STAT);

my $buf = "";
msgctl($id, IPC_STAT, $buf)
    or die "msgctl IPC_STAT failed: $!";

# Layout is platform-dependent; use IPC::SysV helpers to decode.

Συρρικνώστε τον προϋπολογισμό bytes της ουράς. Πλήρης κύκλος μέσω IPC_STAT ώστε τα αμετάβλητα πεδία να διατηρήσουν τις τρέχουσες τιμές τους από τον πυρήνα:

use IPC::SysV qw(IPC_STAT IPC_SET);

my $buf = "";
msgctl($id, IPC_STAT, $buf) or die "stat: $!";
# ... modify msg_qbytes inside $buf via IPC::SysV ...
msgctl($id, IPC_SET,  $buf) or die "set: $!";

Καταστρέψτε μια ουρά όταν τελειώσετε. Το ARG αγνοείται, αλλά πρέπει παρ” όλα αυτά να περαστεί - το 0 είναι ο συμβατικός placeholder:

use IPC::SysV qw(IPC_RMID);

msgctl($qid, IPC_RMID, 0)
    or warn "could not remove queue $qid: $!";

Ιδιωματικός έλεγχος επιτυχίας που λειτουργεί για την περίπτωση "0 but true":

my $rc = msgctl($id, IPC_RMID, 0);
die "msgctl failed: $!" unless defined $rc;   # undef = error
# $rc is now either "0 but true" or a positive integer

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

  • Το IPC::SysV δεν είναι φορτωμένο: γυμνά ονόματα σταθερών όπως IPC_STAT γίνονται barewords και, υπό use strict, σφάλμα κατά τη μεταγλώττιση. Κάνετε πάντα πρώτα use IPC::SysV.

  • Το βαθμωτό που περνά στο IPC_STAT δεν είναι εγγράψιμο: πεθαίνει με Modification of a read-only value attempted. Χρησιμοποιήστε απλό my $buf = "" - όχι σταθερά, όχι κυριολεκτικό συμβολοσειράς.

  • Αναντιστοιχία μήκους στο IPC_SET: αν το ARG είναι μικρότερο από τη msqid_ds του πυρήνα, η κλήση αποτυγχάνει με EFAULT. Ξεκινάτε πάντα από έναν ενταμιευτή IPC_STAT αντί να πακετάρετε έναν από την αρχή.

  • Αφαιρεμένη ουρά (EIDRM): μόλις εκδοθεί η IPC_RMID, οποιαδήποτε περαιτέρω λειτουργία στο ίδιο ID αποτυγχάνει με το $! τεθειμένο σε EIDRM, όχι EINVAL. Σενάρια που κάνουν polling σε ουρά πρέπει να αντιμετωπίζουν το EIDRM ως «η ουρά χάθηκε, σταμάτα».

  • Σφάλματα δικαιωμάτων: οι IPC_SET και IPC_RMID απαιτούν αντιστοίχιση ενεργού UID ή CAP_SYS_ADMIN. Ο πυρήνας επιστρέφει EPERM, όχι EACCES, για αποτυχίες ιδιοκτησίας.

  • Παγίδα τιμής επιστροφής: το if (msgctl(...) == 0) είναι λάθος - σε επιτυχία η τιμή είναι η συμβολοσειρά "0 but true", που μετατρέπεται σε συμβολοσειρά ως μη κενή αλλά συγκρίνεται αριθμητικά ίση με 0. Δοκιμάστε με defined για την περίπτωση σφάλματος, ή βασιστείτε στο or die.

  • Διαθεσιμότητα πλατφόρμας: το System V IPC δεν είναι καθολικό. Σε συστήματα όπου ο πυρήνας το παραλείπει, η msgctl εγείρει την εξαίρεση χρόνου εκτέλεσης msgctl not implemented.

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

Πλήρως συμβατό με το upstream Perl 5.42 σε Linux. Το System V IPC είναι η μόνη υποστηριζόμενη επιφάνεια IPC· η pperl στοχεύει Linux, οπότε οι επιφυλάξεις φορητότητας που απαριθμεί το upstream perlport για μη Linux πλατφόρμες δεν ισχύουν.

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

  • msgget - αποκτήστε το ID ουράς επί του οποίου λειτουργεί η msgctl

  • msgsnd - στείλτε ένα μήνυμα στην ουρά

  • msgrcv - λάβετε ένα μήνυμα από την ουρά

  • semctl - το αντίστοιχο για σύνολο σηματοφόρων, ίδια σύμβαση επιστροφής και ίδιο μοτίβο IPC_STAT / IPC_SET / IPC_RMID

  • shmctl - το αντίστοιχο για τμήμα κοινόχρηστης μνήμης

  • IPC::SysV - οι σταθερές (IPC_STAT, IPC_SET, IPC_RMID) και οι βοηθοί pack/unpack για msqid_ds που απαιτεί αυτή η κλήση