msgctl#
ביצוע פעולת בקרה על תור הודעות System V IPC.
msgctl הוא עטיפה ישירה סביב קריאת המערכת msgctl(2) של C. הוא בוחן, מתקן או מסיר את תור ההודעות המזוהה על־ידי ID. הפעולה שנבחרה על־ידי CMD קובעת כיצד ARG משמש - או כ־descriptor קלט, או כ־buffer פלט, או מתעלמים ממנו לגמרי. הקבועים הסימבוליים הדרושים ל־CMD (IPC_STAT, IPC_SET, IPC_RMID, ובלינוקס IPC_INFO, MSG_STAT, MSG_INFO) נמצאים ב־IPC::SysV, שיש למשוך אותו לפני שהשמות נפתרים.
תקציר#
use IPC::SysV;
msgctl $id, IPC_STAT, $buf # read queue info into $buf
msgctl $id, IPC_SET, $buf # write queue info from $buf
msgctl $id, IPC_RMID, 0 # destroy the queue
מה מקבלים בחזרה#
ערך ההחזרה עוקב אחר אותה מוסכמה כמו ioctl:
המחרוזת
"0 but true"כאשר הקריאה הבסיסית החזירה0. זהו מקרה ההצלחה בעל ערך אפס - הוא נבדק כאמת בהקשר בוליאני ומשווה ל־0בהקשר מספרי, כך שבדיקה אחת מטפלת גם בהצלחה וגם בכישלון.המספר השלם הגולמי השונה מאפס המוחזר אחרת (לדוגמה האינדקס המוחזר על־ידי
MSG_STATהספציפי ללינוקס).
מוסכמת ה־"0 but true" קיימת בדיוק כדי ש־msgctl(...) or die יעשה את הדבר הנכון גם כאשר ה־syscall מחזיר אפס לגיטימית:
msgctl $id, IPC_RMID, 0
or die "msgctl IPC_RMID failed: $!";
כיצד ARG משמש#
ARG ממלא שלושה תפקידים שונים בהתאם ל־CMD. הקרנל נוגע בזיכרון רק בכיוונים שהפקודה דורשת:
IPC_STAT-ARGחייב להיות סקלר בר־כתיבה. הקרנל ממלא אותו במבנהmsqid_dsהארוז המתאר את התור (הרשאות, בעלים, זמני שליחה/קבלה אחרונים, מגבלות בתים של התור, מונים). יש לבצע unpack באמצעות עוזריIPC::SysVבמקום להרכיב את הפריסה ביד;msqid_dsמשתנה בין קרנלים וגרסאות libc.IPC_SET-ARGחייב להכילmsqid_dsארוז שיוצר על־ידיIPC_STATקודם על אותו תור (או תור תואם). רק מספר שדות מכובדים:msg_perm.uid,msg_perm.gid,msg_perm.mode(9 הביטים הנמוכים), ו־msg_qbytes. השאר מתעלמים ממנו.IPC_RMID-ARGאינו בשימוש. יש להעביר0. התור מסומן להשמדה; כלmsgsnd/msgrcvחסום עליו נכשל עםEIDRM.
בלינוקס בלבד, MSG_STAT ו־MSG_INFO מקבלים גם כן סקלר בר־כתיבה עבור ARG ומחזירים נתונים נוספים; אלה אינם ניידים וצריכים להיות מוגנים מאחורי בדיקת זמן ריצה.
מצב גלובלי שהוא נוגע בו#
$!- נקבע בכישלון עם errno של המערכת (EPERM,EACCES,EINVAL,EIDRM,EFAULTהם הערכים הנפוצים).אין משתנים מיוחדים אחרים שנגעים בהם.
דוגמאות#
קריאת כותרת התור ובחינת מגבלת הבתים הנוכחית:
use IPC::SysV qw(IPC_STAT);
my $buf = "";
msgctl($id, IPC_STAT, $buf)
or die "msgctl IPC_STAT failed: $!";
# Layout is platform-dependent; use IPC::SysV helpers to decode.
כיווץ תקציב הבתים של התור. נסיעה הלוך־ושוב דרך IPC_STAT כדי שהשדות הבלתי־משתנים ישמרו על ערכי הקרנל הנוכחיים שלהם:
use IPC::SysV qw(IPC_STAT IPC_SET);
my $buf = "";
msgctl($id, IPC_STAT, $buf) or die "stat: $!";
# ... modify msg_qbytes inside $buf via IPC::SysV ...
msgctl($id, IPC_SET, $buf) or die "set: $!";
השמדת תור בסיום. ARG מתעלמים ממנו, אך עדיין יש להעבירו - 0 הוא מציין־המקום המקובל:
use IPC::SysV qw(IPC_RMID);
msgctl($qid, IPC_RMID, 0)
or warn "could not remove queue $qid: $!";
בדיקת הצלחה אידיומטית שעובדת עבור מקרה ה־"0 but true":
my $rc = msgctl($id, IPC_RMID, 0);
die "msgctl failed: $!" unless defined $rc; # undef = error
# $rc is now either "0 but true" or a positive integer
מקרי קצה#
IPC::SysVלא נטען: שמות קבועים חשופים כמוIPC_STATהופכים ל־barewords, ותחתuse strict, לשגיאת זמן־הידור. תמיד יש לכתובuse IPC::SysVקודם.הסקלר שהועבר ל־
IPC_STATאינו בר־כתיבה: croak עםModification of a read-only value attempted. יש להשתמש ב־my $buf = ""פשוט - לא קבוע, לא ליטרל מחרוזת.אי־התאמת אורך ב־
IPC_SET: אםARGקצר מ־msqid_dsשל הקרנל, הקריאה נכשלת עםEFAULT. תמיד יש להתחיל מ־buffer שלIPC_STATבמקום לארוז אחד מאפס.תור שהוסר (
EIDRM): ברגע ש־IPC_RMIDהוצא, כל פעולה נוספת על אותו ID נכשלת עם$!שנקבע ל־EIDRM, לאEINVAL. סקריפטים שמבצעים polling לתור חייבים להתייחס ל־EIDRMכ־״התור איננו, עצור״.שגיאות הרשאה:
IPC_SETו־IPC_RMIDדורשים התאמת UID אפקטיבי אוCAP_SYS_ADMIN. הקרנל מחזירEPERM, לאEACCES, עבור כישלוני בעלות.מלכודת ערך־החזרה:
if (msgctl(...) == 0)הוא שגוי - בהצלחה הערך הוא המחרוזת"0 but true", שמומרת למחרוזת לא־ריקה אך משווה מספרית ל־0. יש לבדוק עםdefinedעבור מקרה השגיאה, או להסתמך עלor die.זמינות פלטפורמה: System V IPC אינו אוניברסלי. במערכות שבהן הקרנל משמיט אותו,
msgctlמעלה את חריגת זמן־הריצהmsgctl not implemented.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42 בלינוקס. System V IPC הוא משטח ה־IPC היחיד הנתמך; pperl מכוון ללינוקס, ולכן הסתייגויות הניידות ש־perlport של upstream מפרט עבור פלטפורמות שאינן לינוקס אינן חלות.
ראו גם#
msgget- השגת ה־ID של התור ש־msgctlפועל עליוmsgsnd- שליחת הודעה לתורmsgrcv- קבלת הודעה מהתורsemctl- המקבילה למערכת סמפורים, אותה מוסכמת החזרה ואותה תבניתIPC_STAT/IPC_SET/IPC_RMIDshmctl- המקבילה למקטע זיכרון משותףIPC::SysV- הקבועים (IPC_STAT,IPC_SET,IPC_RMID) ועוזרי ה־pack/unpack שלmsqid_dsשקריאה זו דורשת