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 בהצלחה:
המחרוזת
"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(bufferARGשגוי עבור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, לא בתוצאתshmctlshmwrite- העתקת בתים לתוך מקטע מחוברmsgctl- אותו דפוס בקרה לתורי הודעות של System V; אותה מוסכמת החזרה"0 but true"semctl- אותו דפוס בקרה למערכות סמפורים של System V; קבוצתCMDעשירה יותר אך כללי ערך־החזרה זהיםIPC::SysV- מספק את הקבועיםIPC_STAT/IPC_SET/IPC_RMIDואת אורזי ה־shmid_ds