SysV IPC

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:

  • undef בשגיאה, עם $! שנקבע.

  • המחרוזת "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_RMID

  • shmctl - המקבילה למקטע זיכרון משותף

  • IPC::SysV - הקבועים (IPC_STAT, IPC_SET, IPC_RMID) ועוזרי ה־pack/unpack של msqid_ds שקריאה זו דורשת