msgsnd#
Στέλνει ένα μήνυμα σε μια ουρά μηνυμάτων System V IPC.
Η msgsnd είναι ένα λεπτό περιτύλιγμα γύρω από την κλήση συστήματος msgsnd(2). Προσαρτά το MSG στην ουρά που προσδιορίζεται από το ID (το queue id που επέστρεψε προηγουμένως η msgget), και επιστρέφει αληθές σε επιτυχία ή ψευδές σε σφάλμα με ρυθμισμένο το $!. Το MSG δεν είναι ελεύθερης μορφής: πρέπει να ξεκινά με έναν τύπο μηνύματος εγγενούς long, ακολουθούμενο από τα bytes του payload. Τα FLAGS ελέγχουν το μπλοκάρισμα και τη συμπεριφορά σφάλματος-σε-υπερχείλιση, τυπικά 0 ή IPC_NOWAIT.
Σύνοψη#
msgsnd ID, MSG, FLAGS
Τι επιστρέφεται#
Αληθές σε επιτυχία, ψευδές σε αποτυχία. Σε αποτυχία το $! τίθεται στο errno της msgsnd(2) - συνηθισμένες τιμές είναι EAGAIN (ουρά γεμάτη, τέθηκε IPC_NOWAIT), EIDRM (η ουρά αφαιρέθηκε), EINTR (σήμα διέκοψε μπλοκαριστική κλήση), και EACCES (κανένα δικαίωμα εγγραφής στην ουρά).
Επειδή η τιμή επιστροφής είναι απλή λογική τιμή, ελέγξτε την πάντα πριν υποθέσετε ότι το μήνυμα μπήκε στην ουρά:
msgsnd($qid, $msg, 0)
or die "msgsnd($qid) failed: $!";
Μορφή μηνύματος#
Ο πυρήνας δεσμεύει τα πρώτα sizeof(long) bytes κάθε μηνύματος που μπαίνει στην ουρά για τον τύπο μηνύματος, έναν θετικό ακέραιο long που οι καλούντες της msgrcv χρησιμοποιούν για να επιλέξουν ποια μηνύματα να βγάλουν από την ουρά. Το payload ακολουθεί, χωρίς ερμηνεία.
Δημιουργήστε τον ενταμιευτή με την pack χρησιμοποιώντας τους ειδικοποιητές l! (εγγενές long) και a* (ακατέργαστα bytes):
my $type = 1;
my $payload = "hello queue";
my $msg = pack("l! a*", $type, $payload);
msgsnd($qid, $msg, 0) or die "msgsnd: $!";
Ο τύπος μηνύματος πρέπει να είναι μεγαλύτερος από μηδέν. Το μηδέν και οι αρνητικές τιμές είναι δεσμευμένες για τη σημασιολογία επιλογέα της msgrcv και προκαλούν αποτυχία της msgsnd(2) με EINVAL.
Καθολική κατάσταση που επηρεάζει#
$!- τίθεται στοerrnoτης αποτυχημένης κλήσης συστήματος όταν ηmsgsndεπιστρέφει ψευδές. Ανέπαφο σε επιτυχία.
Παραδείγματα#
Αποστολή ενός απλού πληκτρολογημένου μηνύματος με την προεπιλεγμένη μπλοκαριστική συμπεριφορά. Αν η ουρά είναι γεμάτη, η κλήση περιμένει μέχρι να γίνει διαθέσιμος χώρος:
use IPC::SysV qw(IPC_PRIVATE IPC_CREAT S_IRUSR S_IWUSR);
my $qid = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR | S_IWUSR)
// die "msgget: $!";
my $msg = pack("l! a*", 1, "job-42");
msgsnd($qid, $msg, 0) or die "msgsnd: $!";
Αποστολή χωρίς μπλοκάρισμα - άμεση επιστροφή με EAGAIN στο $! αν η ουρά είναι γεμάτη, αντί για ύπνο:
use IPC::SysV qw(IPC_NOWAIT);
use Errno qw(EAGAIN);
unless (msgsnd($qid, $msg, IPC_NOWAIT)) {
if ($! == EAGAIN) {
warn "queue full, dropping message\n";
} else {
die "msgsnd: $!";
}
}
Χρήση του πεδίου τύπου ως ετικέτα προτεραιότητας / καναλιού. Οι παραλήπτες επιλέγουν με βάση τον τύπο μέσω της msgrcv:
my %CHANNEL = (log => 1, metric => 2, alert => 3);
sub send_event {
my ($kind, $body) = @_;
my $msg = pack("l! a*", $CHANNEL{$kind}, $body);
msgsnd($qid, $msg, 0) or die "msgsnd[$kind]: $!";
}
send_event(alert => "disk > 90%");
send_event(metric => "rps=1240");
Αποστολή δομημένου payload - pack-άρετε τα πεδία της επικεφαλίδας μετά το υποχρεωτικό πρόθεμα τύπου:
my $type = 1;
my $body = pack("N N a*", $job_id, $retry_count, $payload);
msgsnd($qid, pack("l! a*", $type, $body), 0)
or die "msgsnd: $!";
Οριακές περιπτώσεις#
Ο τύπος μηνύματος πρέπει να είναι θετικός. Το πέρασμα
0ή αρνητικού τύπου αποτυγχάνει μεEINVAL. Η σημασιολογία επιλογής τύπου στηνmsgrcvδεσμεύει αυτές τις τιμές για λογική επιλογέα.Το μήνυμα υπερβαίνει το
msg_qbytes. Αν τοMSGείναι μεγαλύτερο από το ρυθμισμένο ανά-μήνυμα όριο της ουράς, ηmsgsndαποτυγχάνει μεEINVALανεξαρτήτως τωνFLAGS. Ελέγξτε και ανεβάστε το όριο μεmsgctlIPC_SETαν ελέγχετε την ουρά.Ουρά γεμάτη χωρίς
IPC_NOWAIT. Η κλήση μπλοκάρει μέχρι να βγάλει μήνυμα από την ουρά μια άλλη διεργασία, να αφαιρεθεί η ουρά (EIDRM), ή να την διακόψει σήμα (EINTR). Επαναλάβετε σεEINTRαν το σήμα είναι αναμενόμενο και αβλαβές.Ουρά γεμάτη με
IPC_NOWAIT. Αποτυγχάνει αμέσως μεEAGAIN. Αυτός είναι ο μόνος τρόπος επιβολής φραγμένης καθυστέρησης στην πλευρά της αποστολής.Λείπει το πρόθεμα τύπου. Η παράλειψη
pack-αρίσματος του προθέματος τύπουl!περνά το ακατέργαστο payload ως έχει· τα πρώταsizeof(long)bytes ερμηνεύονται τότε ως τύπος - τυπικά μεγάλος θετικός ή αρνητικός αριθμός - και τα υπόλοιπα ως σώμα. Οι παραλήπτες που φιλτράρουν κατά τύπο δεν βλέπουν τίποτα.Το
IDείναι queue id, όχι κλειδί. Περάστε τον ακέραιο που επιστρέφει ηmsgget, όχι τοKEYπου δώσατε στηνmsgget. Η σύγχυση μεταξύ τους οδηγεί σεEINVALή, χειρότερα, σε επιτυχημένη αποστολή σε άσχετη ουρά που τυχαίνει να μοιράζεται την αριθμητική τιμή.Δικαιώματα. Η διεργασία πρέπει να έχει δικαίωμα εγγραφής στην ουρά (το bit
wτου mode της ουράς για το ενεργό uid/gid της). Διαφορετικά η κλήση αποτυγχάνει μεEACCES.Tainting. Το
MSGδιαβάζεται ως συμβολοσειρά bytes· δεν γίνεται έλεγχος taint σε αυτό εδώ. Αν τοMSGπροήλθε από μη έμπιστη πηγή, η πλευρά παραλήπτη (msgrcv, που όντως taint-άρει την έξοδό της) είναι εκεί όπου ανήκει το φιλτράρισμα.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
msgget- αποκτά το queue id που περνά ωςID· καλέστε αυτό πρώτα, ή λάβετε το id από όποιον δημιούργησε την ουράmsgrcv- η αντίστοιχη πρωτογενής λειτουργία λήψης· το όρισμά τηςTYPEεπιλέγει έναντι του προθέματοςl!που γράφεται εδώmsgctl- επιθεωρεί το όριοmsg_qbytesτης ουράς ή αφαιρεί την ουρά όταν τελειώσετεpack- δημιουργία του ενταμιευτήl! a*που απαιτεί ηmsgsnd· επίσης το εργαλείο για οποιαδήποτε περαιτέρω δομή μέσα στο payload$!- μεταφέρει τοerrnoαπό αποτυχημένηmsgsnd· συγκρίνετε με τις σταθερέςErrnoγια διακλάδωση σε συγκεκριμένες αποτυχίες