SysV IPC

shmctl#

בקרה או תשאול של מקטע זיכרון משותף של System V.

shmctl הוא הפרימיטיב לניהול מקטעי זיכרון משותף שנוצרו עם shmget. הוא מבצע אחת מקבוצה קטנה של פעולות שנקראות על ידי CMD - קריאת המטא־דאטה של המקטע, שינוי ההרשאות שלו, או סימונו להסרה. ID הוא מזהה המקטע שמחזיר shmget. ARG הוא סקלר buffer שמספק מבנה shmid_ds של קלט (עבור IPC_SET) או מקבל את זה שמוחזר (עבור IPC_STAT); עבור IPC_RMID מתעלמים ממנו.

תקציר#

use IPC::SysV qw(IPC_STAT IPC_SET IPC_RMID);

shmctl $id, IPC_STAT, $buf  or die "shmctl STAT: $!";
shmctl $id, IPC_SET,  $buf  or die "shmctl SET: $!";
shmctl $id, IPC_RMID, 0     or die "shmctl RMID: $!";

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

ערך ההחזרה עוקב אחר מוסכמת ioctl, לא דפוס ה־Unix הרגיל של 0 בהצלחה:

  • undef בשגיאה, כאשר $! מוגדר ל־errno.

  • המחרוזת "0 but true" כאשר הקריאה הבסיסית החזירה אפס. זה משווה מספרית שווה ל־0 אבל הוא בוליאני־אמת, כך ש־shmctl(...) or die עדיין עובד.

  • כל ערך לא־אפסי אחר אחרת.

הכלל המעשי: בדקו שקר עם shmctl(...) or die "...: $!" ולעולם אל תשוו את ערך ההחזרה ל־0 ליטרלי עם ==.

הצורה IPC_STAT כותבת מבנה shmid_ds ארוז לתוך ARG. פרקו אותו עם העוזר של IPC::SysV או עם תבנית unpack ידנית; צורת המבנה תלוית־פלטפורמה אז הסתמכות על תבנית קבועה אינה ניידת.

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

  • $! מוגדר בכישלון ל־errno מקריאת shmctl(2) הבסיסית. ערכים אופייניים: EINVAL (ID או CMD שגוי), EACCES (הרשאות לא מספיקות לפעולה), EPERM (לא־בעלים מנסה IPC_SET או IPC_RMID), EFAULT (buffer ARG שגוי עבור IPC_STAT/IPC_SET).

דוגמאות#

קריאת מטא־דאטה של מקטע. IPC::SysV מספק את המפרק shmid_ds; בלעדיו, המבנה הוא מחרוזת בתים אטומה:

use IPC::SysV qw(IPC_STAT);

my $buf = "";
shmctl($id, IPC_STAT, $buf) or die "stat failed: $!";
# $buf now holds the packed shmid_ds structure

שינוי ההרשאות על מקטע קיים. הדפוס הוא קריאה־שינוי־כתיבה על המבנה הארוז:

use IPC::SysV qw(IPC_STAT IPC_SET);

my $buf = "";
shmctl($id, IPC_STAT, $buf) or die $!;
# ... modify the mode bits inside $buf ...
shmctl($id, IPC_SET,  $buf) or die $!;

סימון מקטע להסרה. המקטע נהרס כשהתהליך האחרון מנותק ממנו; IPC_RMID רק מסמן אותו:

use IPC::SysV qw(IPC_RMID);

shmctl($id, IPC_RMID, 0) or die "rmid failed: $!";

שמירה על החזרת "0 but true". מכיוון שמקרה האפס הוא מחרוזת שהיא בוליאנית־אמת, הבדיקה הניבית היא צורת ה־or die, לא השוואה מספרית:

my $rv = shmctl($id, IPC_STAT, $buf);
defined $rv                         or die "error: $!";
# do NOT write: $rv == 0 and ...   # misses the "0 but true" case

מקרי קצה#

  • קבועים חסרים: IPC_STAT, IPC_SET, IPC_RMID אינם מובנים. ללא use IPC::SysV הם קריאות פונקציה של bareword והקוד או נכשל להידור תחת use strict או מעביר בשקט שלם שגוי. תמיד use IPC::SysV qw(...).

  • פעולות בעלים בלבד: IPC_SET ו־IPC_RMID דורשים שה־uid האפקטיבי יתאים ליוצר או לבעלים של המקטע, או שלתהליך יהיה CAP_SYS_ADMIN. אחרת $! הופך ל־EPERM.

  • סמנטיקת IPC_RMID: סימון להסרה אינו מנתק את הקורא ואינו מפסיל חיבורים קיימים. המקטע נשאר שמיש עד שכל תהליך קרא ל־shmdt עליו; רק אז הוא נהרס בפועל. תהליך שמתחבר לאחר IPC_RMID מקבל EIDRM או EINVAL בתלות בתזמון.

  • צורת המבנה אינה ניידת: שדות shmid_ds ו־offsetים משתנים בין קרנלים וגרסאות libc. אל תכתבו ידנית תבניות unpack לסקריפטים שצריכים לרוץ על מספר פלטפורמות; השתמשו ב־IPC::SysV::ShmId או עוטף דומה.

  • גודל buffer עבור IPC_STAT: ARG חייב להיות סקלר של לפחות sizeof(shmid_ds) בתים בפלט. Perl מגדיל אותו לפי הצורך; הגדלה מראש עם $buf = "\0" x 256 נפוצה אך אינה נדרשת.

  • קרנלים לא־מוגדרים: ב־Linux שנבנה ללא CONFIG_SYSVIPC, הקריאה נכשלת עם ENOSYS. תמונות מכולה שמשמיטות SysV IPC מציגות את אותה התנהגות.

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

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

ראו גם#

  • shmget - יצירה או חיפוש של המקטע שעל ה־ID שלו shmctl פועל

  • shmread - העתקת בתים החוצה ממקטע מחובר; משתמש ב־ID שמחזיר shmget, לא בתוצאת shmctl

  • shmwrite - העתקת בתים לתוך מקטע מחובר

  • msgctl - אותו דפוס בקרה לתורי הודעות של System V; אותה מוסכמת החזרה "0 but true"

  • semctl - אותו דפוס בקרה למערכות סמפורים של System V; קבוצת CMD עשירה יותר אך כללי ערך־החזרה זהים

  • IPC::SysV - מספק את הקבועים IPC_STAT / IPC_SET / IPC_RMID ואת אורזי ה־shmid_ds