SysV IPC

shmwrite#

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

shmwrite מתחבר למקטע הזיכרון המשותף המזוהה על־ידי ID, מעתיק עד SIZE בתים מ־STRING החל ב־offset הבתים POS בתוך המקטע, ומתנתק. אם STRING ארוך מ־SIZE, רק SIZE הבתים הראשונים נכתבים; אם הוא קצר יותר, יתרת חלון ה־SIZE בתים מולאית באפסים בבתי NUL. ה־ID של המקטע הוא הערך המוחזר על־ידי קריאת shmget קודמת (או מתקבל מתהליך אחר דרך ערוץ חוץ־רצועה כלשהו).

תקציר#

shmwrite ID, STRING, POS, SIZE

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

אמת בהצלחה, שקר בשגיאה, עם $! שנקבע לסיבה (בדרך כלל EINVAL, EACCES, או EIDRM). בשונה מרוב פונקציות I/O המובנות, ערך־ההחזרה הוא בוליאני רגיל - אין וריאנט של ספירת בתים, מכיוון שהספירה תמיד בדיוק SIZE כשהקריאה מצליחה.

shmwrite($id, $payload, 0, 4096)
    or die "shmwrite($id) failed: $!";

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

  • $! נקבע בכישלון ל־errno של shmat / memcpy / shmdt הבסיסי.

  • אין משתנים מיוחדים אחרים שנקראים או נכתבים. בשונה מ־shmread, shmwrite אינו מכתים דבר - הוא המקור של בתים, לא ה־sink.

דוגמאות#

פרסום רשומה בגודל קבוע בתחילת מקטע:

use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR);
my $id = shmget(IPC_PRIVATE, 4096, S_IRUSR | S_IWUSR)
    or die "shmget: $!";
shmwrite($id, "hello, world", 0, 4096)
    or die "shmwrite: $!";

STRING קצר מ־SIZE מרופד ב־NUL למילוי החלון - שימושי לניקוי בתים מיושנים נסחבים מכותב קודם:

shmwrite($id, "short", 0, 64);   # 5 bytes of "short", then 59 NULs

STRING ארוך מ־SIZE נחתך; הזנב מושלך בשתיקה, ולכן הגדירו את גודל החלון שלכם לרשומה הגדולה ביותר שאתם מתכוונים אי־פעם לפרסם:

shmwrite($id, "x" x 10_000, 0, 128);   # only the first 128 x's land

כתיבה ל־offset לא־אפס מאפשרת למספר רשומות בגודל קבוע לחלוק מקטע אחד. שייכו אותה עם shmread תואם בצד הקורא:

my $slot = 3;
my $len  = 64;
shmwrite($id, $record, $slot * $len, $len)
    or die "shmwrite slot $slot: $!";

בדקו את ערך־ההחזרה - מקטע שסומן למחיקה עם IPC_RMID ממשיך לקבל כתיבות מתהליכים שכבר מחוברים, אך נכשל עבור קריאות shmwrite חדשות עם EIDRM:

unless (shmwrite($id, $msg, 0, $SIZE)) {
    warn "segment $id gone: $!";
    # reacquire via shmget() and retry
}

מקרי קצה#

  • הקרנל חייב להיות בנוי עם SysV IPC. במערכות ללא זיכרון משותף של SysV, shmwrite זורק חריגה עם shmwrite not implemented. זוהי תכונה של זמן הידור של הקרנל / libc, לא תנאי זמן ריצה שתוכלו לבדוק.

  • SIZE של 0 מקובל על־ידי הקרנל ואינו כותב דבר; shmwrite מחזיר אמת. השתמשו בו רק כשאתם באמת מתכוונים ל־״no-op״, לא כאות שגיאה.

  • POS + SIZE חייב להיכנס בתוך המקטע. חריגה מגבול המקטע נכשלת עם EINVAL ומותירה את המקטע ללא שינוי - ההעתקה אינה חלקית.

  • מטענים בינאריים תקינים. STRING מטופל כמחרוזת בתים; NULים מוטמעים נכתבים מילולית. אם המחרוזת נושאת את דגל ה־UTF-8, הבתים הפנימיים הגולמיים הם מה שמגיע למקטע - השתמשו ב־pack או Encode::encode תחילה אם אתם צריכים קידוד ספציפי על החוט.

  • אין נעילה. הקרנל מבטיח שכל קריאת shmwrite היא אטומית ביחס ל־shmat / shmdt, אך שני כותבים בו־זמניים עדיין יכולים לשלב טווחי בתים בתוך המקטע. תאמו עם semop או מנעול במרחב משתמש אם מספר תהליכים כותבים לאותו אזור.

  • הרשאות מגיעות ממצב המקטע בזמן shmget. חיבור לקריאה־בלבד וקריאה ל־shmwrite נכשלת עם EACCES.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • shmread - פעולה הפוכה; מעתיק בתים מתוך מקטע אל סקלר של Perl

  • shmget - משיג את ה־ID ש־shmwrite כותב אליו

  • shmctl - בוחן תכונות מקטע, משנה הרשאות, או מסמן מקטע למחיקה

  • semop - הפרימיטיב המלווה הרגיל לסריאליזציה של גישה למקטע משותף

  • pack - בונה את מחרוזת הבתים בעלת המבנה הקבוע שאתם מוסרים ל־shmwrite כשהמקטע מכיל רשומות מובנות

  • IPC::SysV - קבועים (IPC_PRIVATE, S_IRUSR, IPC_RMID) שמשמשים לבניית הארגומנטים ל־shmget ו־shmctl