msgsnd#
שליחת הודעה לתור הודעות של System V IPC.
msgsnd הוא עטיפה דקה סביב ה־syscall msgsnd(2). הוא מוסיף את MSG לתור המזוהה על־ידי ID (מזהה התור שהוחזר קודם לכן על־ידי msgget), ומחזיר אמת בהצלחה או שקר בשגיאה כאשר $! מוגדר. MSG אינו חופשי בצורתו: עליו להתחיל בסוג הודעת long מקומי, ולאחריו בתי המטען. 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) הבתים הראשונים של כל הודעה בתור עבור סוג ההודעה, מספר שלם חיובי מסוג long שקוראי msgrcv משתמשים בו לבחירת ההודעות שיוצאות מהתור. המטען בא אחריו, ללא פירוש.
בנו את ה־buffer באמצעות pack עם מציינים l! (long מקומי) ו־a* (בתים גולמיים):
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מה־syscall שנכשל כאשר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");
שליחת מטען מובנה - בצעו 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!מעבירה את המטען הגולמי כפי שהוא;sizeof(long)הבתים הראשונים מפורשים אז כסוג - בדרך כלל מספר חיובי או שלילי גדול - והשאר כגוף. מקבלים שמסננים לפי סוג לא רואים דבר.IDהוא מזהה תור, לא מפתח. העבירו את המספר השלם שהוחזר על־ידיmsgget, לא את ה־KEYשניתן ל־msgget. בלבול בין השניים מניבEINVALאו, גרוע יותר, שליחה מוצלחת לתור לא־קשור שבמקרה חולק את הערך המספרי.הרשאות. לתהליך חייבת להיות הרשאת כתיבה על התור (סיבית ה־
wשל מצב התור עבור ה־uid/gid האפקטיבי שלו). אחרת הקריאה נכשלת עםEACCES.Tainting.
MSGנקרא כמחרוזת בתים; אין מבצעים בדיקת taint עליו כאן. אםMSGהגיע ממקור לא־מהימן, צד המקבל (msgrcv, שכן מכתים את הפלט שלו) הוא המקום למסנן.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
msgget- השגת מזהה התור המועבר כ־ID; קראו לכך תחילה, או קבלו את המזהה ממי שיצר את התורmsgrcv- פרימיטיב הקבלה המתאים; הארגומנטTYPEשלו בורר מול קידומת ה־l!הנכתבת כאןmsgctl- בחנו את גבול ה־msg_qbytesשל התור או הסירו את התור בסיוםpack- בניית ה־bufferl! a*ש־msgsndדורש; גם הכלי לכל מבנה נוסף בתוך המטען$!- נושא את ה־errnoמ־msgsndשנכשל; השוו מול קבועיErrnoכדי להסתעף על כשלים ספציפיים