SysV IPC

msgget#

יוצר או מחפש תור הודעות של System V IPC ומחזיר את ה־id שלו.

msgget הוא נקודת הכניסה למשפחת תורי ההודעות של System V: כל קריאת msgsnd, msgrcv, או msgctl מאוחרת זקוקה ל־id, ומכאן ה־id הזה מגיע. KEY מנקב את התור על פני המערכת כולה (מספר שלם key_t, נבנה בדרך כלל עם IPC::SysV::ftok או הערך המיוחד IPC_PRIVATE). FLAGS הוא bitwise-or של ביטי הרשאות (התשעה הנמוכים, פריסה זהה למצבי קבצים) ודגלים אופציונליים IPC_CREAT / IPC_EXCL. הקריאה היא עטיפה ישירה סביב הקריאת מערכת msgget(2).

תקציר#

use IPC::SysV qw(IPC_CREAT IPC_EXCL IPC_PRIVATE S_IRUSR S_IWUSR);

my $id = msgget($key, IPC_CREAT | 0600);
my $id = msgget(IPC_PRIVATE, 0600);
my $id = msgget($key, IPC_CREAT | IPC_EXCL | 0600);

מה מקבלים בחזרה#

מספר שלם לא־שלילי כ־id של תור הודעות בהצלחה, או undef בכישלון (כש־$! מוגדר לערך ה־errno מקריאת המערכת הבסיסית). ה־id הוא ידית אטומה - אל תבצע חשבון עליו, פשוט העבר אותו בחזרה למובנים האחרים msg*.

my $id = msgget($key, IPC_CREAT | 0600)
    // die "msgget($key) failed: $!";

מצב גלובלי שהוא נוגע בו#

  • $! - מוגדר בכישלון ל־errno מ־msgget(2) (בדרך כלל EACCES, EEXIST, ENOENT, ENOSPC, ENOMEM).

שום משתנים מיוחדים אחרים אינם מעורבים. התור עצמו חי בקרנל, לא בתהליך Perl, ומתמיד דרך exec ולאחר שהתהליך היוצר יוצא - יש להסיר אותו במפורש עם msgctl ו־IPC_RMID.

דוגמאות#

יצירת תור פרטי ששום תהליך אחר אינו יכול לנקוב - הבחירה הרגילה כאשר התור משותף רק עם ילדי תהליך זה:

use IPC::SysV qw(IPC_PRIVATE);
my $id = msgget(IPC_PRIVATE, 0600) // die "msgget: $!";

יצירה או חיבור לתור בעל שם תוך שימוש ב־key_t הנגזר מנתיב קובץ. ftok הופך נתיב פלוס id פרויקט בעל תו יחיד למפתח יציב כך שתהליכים לא־קשורים יכולים להסכים על תור:

use IPC::SysV qw(ftok IPC_CREAT);
my $key = ftok("/var/run/myapp", 'M');
my $id  = msgget($key, IPC_CREAT | 0600) // die "msgget: $!";

יצירה בלעדית - כשל אם התור כבר קיים. כך מזהים שמופע קודם של התוכנית שלך עדיין בסביבה:

use IPC::SysV qw(IPC_CREAT IPC_EXCL);
my $id = msgget($key, IPC_CREAT | IPC_EXCL | 0600);
if (!defined $id) {
    die "queue already exists" if $!{EEXIST};
    die "msgget: $!";
}

חיבור לתור קיים ללא יצירה - השמט את IPC_CREAT. מחזיר undef עם $! מוגדר ל־ENOENT אם תור כזה אינו קיים:

my $id = msgget($key, 0) // die "no queue for key $key: $!";

הסרת התור בסיום. ל־msgget עצמו אין מקבילה לפירוק; ההסרה עוברת דרך msgctl:

use IPC::SysV qw(IPC_RMID);
msgctl($id, IPC_RMID, 0) or warn "msgctl IPC_RMID: $!";

מקרי קצה#

  • KEY חייב להיות מספר שלם, בדרך כלל key_t. העברת מחרוזת מפעילה את כללי ההמרה המספרית הרגילים ותנקוב כמעט בוודאות בתור הלא־נכון. בנה מפתחות עם IPC::SysV::ftok או השתמש ב־IPC_PRIVATE.

  • IPC_PRIVATE תמיד יוצר תור חדש, ללא קשר אם IPC_CREAT מוגדר. המפתח אינו ניתן לשימוש חוזר - אינך יכול msgget את אותו תור מאוחר יותר מתהליך לא־קשור באמצעות IPC_PRIVATE.

  • ביטי הרשאות חלים בכל קריאה, לא רק ביצירה. חיבור לתור קיים ללא IPC_CREAT עדיין בודק את ביטי ההרשאות מול הבעלים/קבוצה של התור ו־uid/gid האפקטיביים של התהליך הנוכחי. ביטים לא־תואמים נותנים EACCES.

  • IPC_EXCL ללא IPC_CREAT הוא חסר־משמעות - הקרנל מתעלם ממנו. אם אתה רוצה יצירה בלעדית, תמיד התאם ביניהם.

  • מגבלות כלל־מערכת. יצירה יכולה להיכשל עם ENOSPC כאשר נוגעים במגבלת MSGMNI של הקרנל, או ENOMEM תחת לחץ זיכרון. אלה אינם באגים בתוכנית שלך; אלה תנאי הפעלה.

  • משך חיי התור עולה על חיי תהליכים. תור שנוצר כאן מתמיד עד הסרה מפורשת עם msgctl ו־IPC_RMID, או עד שהמערכת מבצעת אתחול. תורים נשכחים מדלפים משאבי קרנל ש־ipcs ו־ipcrm משמשים למצוא ולנקות.

  • לא לכל המערכות יש תורי הודעות SysV. בפלטפורמות המשמיטות אותם, המובנה עושה croak עם msgget not implemented on this architecture. אזהרת הניידות ב־POD המקורי חלה.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • msgsnd - שולח הודעה לתור שמחזיר msgget

  • msgrcv - מקבל הודעה מאותו תור

  • msgctl - מתשאל, מגדיר אפשרויות, או מסיר את התור; הפירוק לאחר msgget עובר כאן

  • semget - אותה צורת API לסמפורי System V כשאתה צריך סנכרון במקום העברת נתונים

  • shmget - אותה צורת API לזיכרון משותף של System V כשאתה צריך שיתוף זיכרון ישיר במקום העברת הודעות

  • IPC::SysV - מספק את ftok ואת הקבועים IPC_* / S_* ש־msgget מצפה להם ב־FLAGS