SysV IPC

shmctl#

Έλεγχος ή ερώτηση τμήματος κοινόχρηστης μνήμης System V.

Η shmctl είναι η πρωτογενής λειτουργία διαχείρισης για τμήματα κοινόχρηστης μνήμης που έχουν δημιουργηθεί με την shmget. Εκτελεί μία από μια μικρή σειρά λειτουργιών που ονομάζονται μέσω του CMD - ανάγνωση των μεταδεδομένων του τμήματος, αλλαγή των δικαιωμάτων του, ή σήμανση για αφαίρεση. Το ID είναι το αναγνωριστικό τμήματος που επιστρέφει η shmget. Το ARG είναι βαθμωτός ενταμιευτής που είτε παρέχει εισερχόμενη δομή shmid_ds (για IPC_SET) είτε λαμβάνει την επιστρεφόμενη (για IPC_STAT)· για IPC_RMID αγνοείται.

Σύνοψη#

use IPC::SysV qw(IPC_STAT IPC_SET IPC_RMID);

shmctl $id, IPC_STAT, $buf  or die "shmctl STAT: $!";
shmctl $id, IPC_SET,  $buf  or die "shmctl SET: $!";
shmctl $id, IPC_RMID, 0     or die "shmctl RMID: $!";

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

Η τιμή επιστροφής ακολουθεί τη σύμβαση της ioctl, όχι το συνηθισμένο μοτίβο Unix 0-σε-επιτυχία:

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

  • Η συμβολοσειρά "0 but true" όταν η υποκείμενη κλήση επέστρεψε μηδέν. Αυτή συγκρίνεται αριθμητικά ίση με 0 αλλά είναι αληθής λογικά, οπότε το shmctl(...) or die εξακολουθεί να λειτουργεί.

  • Οποιαδήποτε άλλη μη μηδενική τιμή διαφορετικά.

Ο πρακτικός κανόνας: ελέγξτε για ψεύδος με shmctl(...) or die "...: $!" και ποτέ μη συγκρίνετε την τιμή επιστροφής με κυριολεκτικό 0 μέσω ==.

Η μορφή IPC_STAT γράφει πακεταρισμένη δομή shmid_ds στο ARG. Αποπακετάρετέ την με το βοηθητικό του IPC::SysV ή με χειροκίνητο πρότυπο unpack· η διάταξη της δομής εξαρτάται από την πλατφόρμα οπότε η εξάρτηση από σταθερό πρότυπο δεν είναι φορητή.

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

  • Το $! τίθεται σε αποτυχία στο errno από την υποκείμενη κλήση shmctl(2). Τυπικές τιμές: EINVAL (κακό ID ή CMD), EACCES (ανεπαρκή δικαιώματα για τη λειτουργία), EPERM (μη ιδιοκτήτης που επιχειρεί IPC_SET ή IPC_RMID), EFAULT (κακός ενταμιευτής ARG για IPC_STAT/IPC_SET).

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

Ανάγνωση μεταδεδομένων τμήματος. Το IPC::SysV παρέχει τον αποπακετάρο shmid_ds· χωρίς αυτό, η δομή είναι αδιαφανής συμβολοσειρά bytes:

use IPC::SysV qw(IPC_STAT);

my $buf = "";
shmctl($id, IPC_STAT, $buf) or die "stat failed: $!";
# $buf now holds the packed shmid_ds structure

Αλλαγή των δικαιωμάτων σε υπάρχον τμήμα. Το μοτίβο είναι ανάγνωση-τροποποίηση-εγγραφή στην πακεταρισμένη δομή:

use IPC::SysV qw(IPC_STAT IPC_SET);

my $buf = "";
shmctl($id, IPC_STAT, $buf) or die $!;
# ... modify the mode bits inside $buf ...
shmctl($id, IPC_SET,  $buf) or die $!;

Σήμανση τμήματος για αφαίρεση. Το τμήμα καταστρέφεται μόλις αποσυνδεθεί η τελευταία διεργασία από αυτό· το IPC_RMID μόνο το σημαίνει:

use IPC::SysV qw(IPC_RMID);

shmctl($id, IPC_RMID, 0) or die "rmid failed: $!";

Φύλαξη βάσει της επιστροφής "0 but true". Επειδή η περίπτωση μηδενός είναι συμβολοσειρά που είναι λογικά αληθής, ο ιδιωματικός έλεγχος είναι η μορφή or die, όχι αριθμητική σύγκριση:

my $rv = shmctl($id, IPC_STAT, $buf);
defined $rv                         or die "error: $!";
# do NOT write: $rv == 0 and ...   # misses the "0 but true" case

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

  • Σταθερές που λείπουν: τα IPC_STAT, IPC_SET, IPC_RMID δεν είναι ενσωματωμένα. Χωρίς use IPC::SysV είναι κλήσεις συνάρτησης bareword και ο κώδικας είτε αποτυγχάνει στη μεταγλώττιση υπό use strict είτε σιωπηρά περνά τον λάθος ακέραιο. Πάντα use IPC::SysV qw(...).

  • Λειτουργίες μόνο για τον ιδιοκτήτη: τα IPC_SET και IPC_RMID απαιτούν το effective uid να ταιριάζει με τον δημιουργό ή τον ιδιοκτήτη του τμήματος, ή η διεργασία να έχει CAP_SYS_ADMIN. Διαφορετικά το $! γίνεται EPERM.

  • Σημασιολογία IPC_RMID: η σήμανση για αφαίρεση δεν αποσυνδέει τον καλούντα και δεν ακυρώνει τις υπάρχουσες συνδέσεις. Το τμήμα παραμένει χρησιμοποιήσιμο μέχρι κάθε διεργασία να καλέσει shmdt σε αυτό· μόνο τότε καταστρέφεται πραγματικά. Μια διεργασία που συνδέεται μετά το IPC_RMID λαμβάνει EIDRM ή EINVAL ανάλογα με τον χρονισμό.

  • Η διάταξη της δομής δεν είναι φορητή: τα πεδία και τα offsets του shmid_ds διαφέρουν μεταξύ πυρήνων και εκδόσεων libc. Μην γράφετε χειροκίνητα πρότυπα unpack για σενάρια που πρέπει να τρέξουν σε πολλές πλατφόρμες· χρησιμοποιήστε IPC::SysV::ShmId ή παρόμοιο περιτύλιγμα.

  • Διαστασιολόγηση ενταμιευτή για IPC_STAT: το ARG πρέπει να είναι βαθμωτό τουλάχιστον sizeof(shmid_ds) bytes στην έξοδο. Η Perl το μεγαλώνει όπως χρειάζεται· η προ-διαστασιολόγηση με $buf = "\0" x 256 είναι συνηθισμένη αλλά όχι απαραίτητη.

  • Μη διαμορφωμένοι πυρήνες: σε Linux που έχει χτιστεί χωρίς CONFIG_SYSVIPC, η κλήση αποτυγχάνει με ENOSYS. Container images που εξαιρούν το SysV IPC εμφανίζουν την ίδια συμπεριφορά.

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

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

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

  • shmget - δημιουργία ή αναζήτηση του τμήματος του οποίου το ID χειρίζεται η shmctl

  • shmread - αντιγραφή bytes από συνδεδεμένο τμήμα· χρησιμοποιεί το ID που επιστρέφει η shmget, όχι αποτέλεσμα της shmctl

  • shmwrite - αντιγραφή bytes σε συνδεδεμένο τμήμα

  • msgctl - ίδιο μοτίβο ελέγχου για ουρές μηνυμάτων System V· ίδια σύμβαση επιστροφής "0 but true"

  • semctl - ίδιο μοτίβο ελέγχου για σύνολα σηματοφόρων System V· πλουσιότερο σύνολο CMD αλλά πανομοιότυποι κανόνες τιμής επιστροφής

  • IPC::SysV - παρέχει τις σταθερές IPC_STAT / IPC_SET / IPC_RMID και τους πακετάρους shmid_ds