msgrcv#
לקבל הודעה מתור הודעות System V IPC.
msgrcv הוא הקישור של Perl ל־syscall msgrcv(2). הוא מושך הודעה אחת מהתור שמזוהה על־ידי ID, מאחסן את סוג ההודעה ואת ה־payload לתוך VAR, ומחזיר ערך אמת בהצלחה או שקר בשגיאה. SIZE הוא המספר המקסימלי של בתי payload שהקורא מוכן לקבל; TYPE בוחר איזו הודעה לקבל; FLAGS הוא ה־bitmask שמועבר לקרנל (IPC_NOWAIT, MSG_NOERROR, וכו«).
המאגר המוחזר אינו רק גוף ההודעה - sizeof(long) הבתים הראשונים הם סוג ההודעה שהשולח העביר ל־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 נדרס במסגרת שהתקבלה: long נטיבי (סוג ההודעה) ומיד אחריו עד SIZE בתים של payload. המשתנה מסומן tainted תחת -T.
VAR מוגדל או מוקטן כדי להתאים לאורך המסגרת בפועל - אין צורך לקבוע לו גודל מראש. התוכן לפני הקריאה מושלך.
לקבלת הסוג וה־payload כערכים נפרדים:
my ($type, $msg) = unpack "l! a*", $buf;
ארגומנטים#
ID- מזהה התור שהוחזר קודם לכן על־ידיmsgget.VAR- סקלר lvalue שמקבל את המסגרת הגולמית. הערך הקודם שלו מושלך בהצלחה.SIZE- גודל ה־payload המקסימלי בבתים. אם ההודעה התואמת הבאה גדולה מזה,msgrcvנכשל עםE2BIGוההודעה נשארת בתור - אלא אםMSG_NOERRORמוגדר ב־FLAGS, ובמקרה זה ההודעה נחתכת בשקט והבתים הנוספים אובדים.TYPE- בוחר איזו הודעה לקבל:0- ההודעה הראשונה בתור, לא משנה הסוג שלה.Nחיובי - ההודעה הראשונה שסוגה הוא בדיוקN.-Nשלילי - ההודעה הראשונה של הסוג הנמוך ביותר שהוא<= abs(N), שימושי לתורי עדיפויות.
FLAGS- bitmask שלIPC_NOWAIT(להחזירENOMSGמיד במקום לחסום כאשר אין הודעה תואמת זמינה),MSG_NOERROR(לחתוך במקום להיכשל על הודעות גדולות מדי), ו־MSG_EXCEPTהספציפי ל־Linux (עםTYPEחיובי, לקבל את ההודעה הראשונה שסוגה אינוTYPE).
הקבועים חיים ב־IPC::SysV; השמות החשופים אינם נראים עד שמייבאים אותם.
מצב גלובלי שהוא נוגע בו#
$!- מוגדר בשגיאה ל־errnoהבסיסי (ENOMSG,E2BIG,EIDRM,EINVAL,EACCES,EFAULT,EINTR).מצב taint -
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.פריסת המסגרת היא
longנטיבי, לא ארבעה בתים. ב־Linux 64-bit הסוג תופס 8 בתים; במערכות 32-bit הוא תופס 4. ה־l!ב־unpack "l! a*"- ה־!- חובה;lפשוט מניח 4 בתים ויפגע ב־payloads על מארחי 64-bit.SIZEאינו כולל את כותרת הסוג לצרכיMSG_NOERROR. הקרנל משווה אתSIZEמול אורך ה־payload, לא אורך המסגרת. יש לקבוע את גודל המאגר עבור ה־payload הגדול ביותר שמצפים לו; כותרת הסוג נכתבת מעבר לכך.הפסקת אות.
msgrcvחוסם מחזיר שקר עם$! == EINTRכאשר אות מגיע לפני שהודעה זמינה. יש לנסות שוב את הקריאה אלא אם האות נועד לבטל את לולאת הקבלה.התור הוסר בעת חסימה. אם תהליך אחר קורא ל־
msgctlעםIPC_RMIDבעוד תהליך זה ישן ב־msgrcv, הקריאה מחזירה שקר עם$! == EIDRM.הרשאות. קבלה דורשת הרשאת קריאה על התור.
EACCESמשמעו שהתור קיים אך ה־uid/gid הנוכחי אינו תואם את ביטי המצב של התור.TYPE = 0רואה סדר FIFO. אין עדיפות ״כל אחד״ פחות מ־TYPEשלילי מפורש - הודעות מכל הסוגים נמשכות בסדר השליחה.תמיכת קרנל. קרנלי Linux שנבנו ללא
CONFIG_SYSVIPC, ו־container runtimes שלא חושפים את ה־namespace של IPC, נכשלים בכלmsgrcvעםENOSYS. יש לבדוק בעת האתחול אם יעד הפריסה אינו ודאי.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
msgsnd- המקבילה ששמה הודעות על התור; התבניתpack "l! a*"שלה היא ההפוכה של מה ש־unpackכאןmsgget- להשיג את מזהה התורIDשמעבירים פנימהmsgctl- לבחון או למחוק את התור, כולל ה־IPC_RMIDשגורם ל־msgrcvחסום להחזירEIDRMunpack- לפצל את המסגרת המוחזרת לסוג ו־payload עםl! a*IPC::SysV- מקור שלIPC_NOWAIT,MSG_NOERROR, וקבועי דגלים קשוריםIPC::Msg- עטיפה מונחית־עצמים שמסתירה את ריקוד ה־pack/unpack מאחורי מתודתrcv