SysV IPC

msgrcv#

Λήψη μηνύματος από ουρά μηνυμάτων System V IPC.

Η msgrcv είναι η σύνδεση Perl για την κλήση συστήματος msgrcv(2). Αντλεί ένα μήνυμα από την ουρά που προσδιορίζεται από το ID, αποθηκεύει τον τύπο μηνύματος και το payload στο VAR, και επιστρέφει αληθή τιμή σε επιτυχία ή ψευδή σε σφάλμα. Το SIZE είναι ο μέγιστος αριθμός bytes payload που ο καλών είναι διατεθειμένος να αποδεχτεί· το TYPE επιλέγει ποιο μήνυμα θα ληφθεί· το FLAGS είναι η bitmask που περνά στον πυρήνα (IPC_NOWAIT, MSG_NOERROR, κ.λπ.).

Ο επιστρεφόμενος buffer δεν είναι μόνο το σώμα του μηνύματος - τα πρώτα sizeof(long) bytes είναι ο τύπος μηνύματος που πέρασε ο αποστολέας στην msgsnd, ακολουθούμενα από το payload. Χρησιμοποιήστε unpack με πρότυπο l! a* για να τα διαχωρίσετε.

Σύνοψη#

use IPC::SysV qw(IPC_NOWAIT MSG_NOERROR);

msgrcv $qid, my $buf, 1024, 0, 0            or die "msgrcv: $!";
msgrcv $qid, my $buf, 1024, 0, IPC_NOWAIT;  # non-blocking
my ($type, $payload) = unpack "l! a*", $buf;

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

Αληθές σε επιτυχία, ψευδές σε σφάλμα με την $! ορισμένη. Σε επιτυχία, το VAR αντικαθίσταται με το ληφθέν frame: ένα native long (ο τύπος μηνύματος) ακολουθούμενο άμεσα από έως SIZE bytes payload. Η μεταβλητή σημειώνεται ως tainted υπό -T.

Το VAR επεκτείνεται ή συρρικνώνεται για να χωρέσει το πραγματικό μήκος του frame - δεν χρειάζεται να το προδιαστασιολογήσετε. Το περιεχόμενο πριν την κλήση απορρίπτεται.

Για να λάβετε τον τύπο και το payload ως ξεχωριστές τιμές:

my ($type, $msg) = unpack "l! a*", $buf;

Ορίσματα#

  • ID - το id ουράς που επιστράφηκε προηγουμένως από την msgget.

  • VAR - ένα lvalue βαθμωτό που λαμβάνει το αδρό frame. Η προηγούμενη τιμή του απορρίπτεται σε επιτυχία.

  • SIZE - το μέγιστο μέγεθος payload σε bytes. Αν το επόμενο μήνυμα που ταιριάζει είναι μεγαλύτερο από αυτό, η msgrcv αποτυγχάνει με E2BIG και το μήνυμα παραμένει στην ουρά - εκτός αν είναι ορισμένο το MSG_NOERROR στα FLAGS, οπότε το μήνυμα αποκόπτεται σιωπηρά και τα επιπλέον bytes χάνονται.

  • TYPE - επιλέγει ποιο μήνυμα θα ληφθεί:

    • 0 - το πρώτο μήνυμα στην ουρά, ανεξάρτητα από τον τύπο του.

    • θετικό N - το πρώτο μήνυμα του οποίου ο τύπος είναι ακριβώς N.

    • αρνητικό -N - το πρώτο μήνυμα του χαμηλότερου τύπου που είναι <= abs(N), χρήσιμο για ουρές προτεραιότητας.

  • FLAGS - bitmask από IPC_NOWAIT (άμεση επιστροφή ENOMSG αντί για μπλοκάρισμα όταν δεν υπάρχει διαθέσιμο μήνυμα που ταιριάζει), MSG_NOERROR (αποκοπή αντί για αποτυχία σε υπερμεγέθη μηνύματα), και τη Linux-ειδική MSG_EXCEPT (με θετικό TYPE, λήψη του πρώτου μηνύματος του οποίου ο τύπος δεν είναι TYPE).

Οι σταθερές βρίσκονται στο IPC::SysV· τα σκέτα ονόματα δεν γίνονται ορατά μέχρι να τα εισάγετε.

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

  • $! - τίθεται σε σφάλμα στο υποκείμενο errno (ENOMSG, E2BIG, EIDRM, EINVAL, EACCES, EFAULT, EINTR).

  • Taint mode - το ληφθέν VAR σημειώνεται ως tainted, αφού το περιεχόμενό του προήλθε από άλλη διεργασία.

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

Λήψη με μπλοκάρισμα οποιουδήποτε μηνύματος, και έπειτα διαχωρισμός τύπου και payload:

use IPC::SysV qw(IPC_CREAT S_IRUSR S_IWUSR);

my $qid = msgget(IPC_PRIVATE, S_IRUSR | S_IWUSR) // die "msgget: $!";
msgrcv $qid, my $buf, 4096, 0, 0            or die "msgrcv: $!";
my ($type, $payload) = unpack "l! a*", $buf;
print "got type=$type payload=$payload\n";

Λήψη μόνο μηνυμάτων τύπου 42:

msgrcv $qid, my $buf, 4096, 42, 0           or die "msgrcv: $!";

Δημοσκόπηση χωρίς μπλοκάρισμα - άμεση επιστροφή αν η ουρά είναι κενή:

use IPC::SysV qw(IPC_NOWAIT);
use Errno qw(ENOMSG);

if (msgrcv $qid, my $buf, 4096, 0, IPC_NOWAIT) {
    my ($type, $msg) = unpack "l! a*", $buf;
    handle($type, $msg);
} elsif ($! == ENOMSG) {
    # queue was empty; try again later
} else {
    die "msgrcv: $!";
}

Αποκοπή υπερμεγέθων μηνυμάτων αντί για αποτυχία:

use IPC::SysV qw(MSG_NOERROR);

msgrcv $qid, my $buf, 64, 0, MSG_NOERROR    or die "msgrcv: $!";
# payload is at most 64 bytes, excess discarded without error

Λήψη τύπου προτεραιότητας - λήψη του μηνύματος με τον χαμηλότερο αριθμό του οποίου ο τύπος είναι <= 3:

msgrcv $qid, my $buf, 4096, -3, 0           or die "msgrcv: $!";

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

  • Το VAR πρέπει να είναι lvalue. Το πέρασμα σταθεράς ή βαθμωτού μόνο για ανάγνωση (για παράδειγμα ένα στοιχείο του @_ που πέρασε με αναφορά σε κυριολεκτικό) εγείρει Modification of a read-only value attempted.

  • Η διάταξη του frame είναι native long, όχι τέσσερα bytes. Σε 64-bit Linux ο τύπος καταλαμβάνει 8 bytes· σε 32-bit συστήματα καταλαμβάνει 4. Το l! στο unpack "l! a*" - το ! - είναι υποχρεωτικό· ένα σκέτο l υποθέτει 4 bytes και θα διαφθείρει payloads σε 64-bit υπολογιστές.

  • Το SIZE εξαιρεί την επικεφαλίδα τύπου για σκοπούς του MSG_NOERROR. Ο πυρήνας συγκρίνει το SIZE με το μήκος του payload, όχι του frame. Διαστασιολογήστε τον buffer για το μεγαλύτερο payload που αναμένετε· η επικεφαλίδα τύπου γράφεται πέρα από αυτό.

  • Διακοπή σήματος. Μια μπλοκαριστική msgrcv επιστρέφει ψευδές με $! == EINTR όταν φτάνει σήμα πριν να είναι διαθέσιμο μήνυμα. Επαναλάβετε την κλήση εκτός αν το σήμα προορίζεται να ματαιώσει τον βρόχο λήψης.

  • Αφαίρεση ουράς ενώ είναι μπλοκαρισμένη. Αν άλλη διεργασία καλέσει msgctl με IPC_RMID ενώ αυτή η διεργασία κοιμάται στην msgrcv, η κλήση επιστρέφει ψευδές με $! == EIDRM.

  • Δικαιώματα. Η λήψη απαιτεί δικαίωμα ανάγνωσης στην ουρά. Το EACCES σημαίνει ότι η ουρά υπάρχει αλλά τα τρέχοντα uid/gid δεν ταιριάζουν με τα mode bits της ουράς.

  • Το TYPE = 0 βλέπει σειρά FIFO. Δεν υπάρχει προτεραιότητα «οποιοδήποτε» πέραν του ρητού αρνητικού TYPE - μηνύματα όλων των τύπων αντλούνται με σειρά αποστολής.

  • Υποστήριξη πυρήνα. Πυρήνες Linux χτισμένοι χωρίς CONFIG_SYSVIPC, και container runtimes που δεν εκθέτουν τον χώρο ονομάτων IPC, αποτυγχάνουν κάθε msgrcv με ENOSYS. Ελέγξτε κατά την εκκίνηση αν ο στόχος ανάπτυξής σας είναι αβέβαιος.

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

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

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

  • msgsnd - η αντίστοιχη που τοποθετεί μηνύματα στην ουρά· το πρότυπο pack "l! a*" της είναι το αντίστροφο αυτού που κάνετε unpack εδώ

  • msgget - απόκτηση του id ουράς ID που περνάτε

  • msgctl - επιθεώρηση ή διαγραφή της ουράς, συμπεριλαμβανομένου του IPC_RMID που προκαλεί επιστροφή EIDRM από μπλοκαρισμένη msgrcv

  • unpack - διαχωρισμός του επιστρεφόμενου frame σε τύπο και payload με l! a*

  • IPC::SysV - πηγή των σταθερών σημαίας IPC_NOWAIT, MSG_NOERROR και σχετικών

  • IPC::Msg - αντικειμενοστρεφές περιτύλιγμα που αποκρύπτει τη διαδικασία pack/unpack πίσω από μια μέθοδο rcv