SysV IPC

shmread#

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

shmread נצמד למקטע הזיכרון המשותף שמזוהה על־ידי ID, קורא SIZE בתים החל מ־offset הבתים POS, כותב אותם לתוך VAR, ומתנתק. ל־VAR נעשית השמה כאל שלם - כל מה שהחזיק לפני מוחלף בדיוק ב־SIZE בתים של נתונים. המשתנה מסומן מוכתם תחת -T, מאחר שתוכנו הגיע מחוץ לתוכנית.

תקציר#

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

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

ערך־אמת בהצלחה, שקר בכישלון כש־$! מוגדר. בהצלחה VAR נדרס בדיוק ב־SIZE בתים; אין קריאות קצרות - או שכל הטווח מועתק פנימה או שהקריאה נכשלת. בכישלון תוכן VAR אינו מוגדר; אל תסתמך עליו.

תמיד בדוק את ערך ההחזרה. ID רע, POS/SIZE מחוץ לטווח, או מקטע שלתהליך חסרה הרשאה להיצמד אליו, כולם צצים כאן כהחזרת שקר:

shmread($id, my $buf, $pos, $size)
    or die "shmread(id=$id, pos=$pos, size=$size): $!";

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

  • $! - מוגדר בכישלון (כל אחת משגיאות shmat/memcpy/shmdt הבסיסיות צצה כאן).

  • דגל taint על VAR - מוגדר תחת -T ללא קשר לאופן שבו VAR הוצהר, מכיוון שהבתים מקורם מחוץ לתוכנית.

דוגמאות#

קריאת רשומה בגודל קבוע ממקטע:

use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR);
my $id = shmget(IPC_PRIVATE, 1024, S_IRUSR | S_IWUSR) or die "shmget: $!";
shmwrite($id, "hello, world", 0, 12)                  or die "shmwrite: $!";
shmread($id, my $buf, 0, 12)                          or die "shmread: $!";
print $buf, "\n";                                     # hello, world

קריאה ב־offset. POS ו־SIZE הם בבתים, לא באלמנטים - למקטע אין מושג של רשומות:

shmread($id, my $chunk, 256, 64)
    or die "shmread: $!";                             # bytes 256..319

פענוח רשומה בינארית ישירות מהזיכרון המשותף:

shmread($id, my $raw, 0, 16) or die "shmread: $!";
my ($magic, $len, $flags) = unpack "a4 N N", $raw;

קריאת נתונים מוכתמים תחת -T. ההשמה מובטחת להפיק סקלר מוכתם גם אם VAR כבר החזיק ערך לא־מוכתם:

# perl -T
shmread($id, my $buf, 0, $n) or die "shmread: $!";
# $buf is tainted; untaint via a regex match before using
# it in a sensitive context.

מקרי קצה#

  • ל־VAR נעשית השמה, לא צירוף לסוף. כל ערך קודם מושלך. השתמש ב־lexical רענן אם אתה צריך גם נתונים ישנים וגם חדשים.

  • SIZE הוא מדויק, לא מקסימום. shmread אינו עושה קריאות קצרות; בקשת בתים יותר ממה שהמקטע מחזיק מ־POS והלאה נכשלת במקום להחזיר את מה שמתאים.

  • POS ו־SIZE חייבים לשכון בתוך המקטע שהוכרז בזמן shmget. POS + SIZE מעבר לסוף המקטע נכשל עם EINVAL.

  • SIZE אפס מפיק מחרוזת ריקה ב־VAR ומצליח, בהנחה ש־POS עצמו תקף.

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

  • VAR אינו חייב להיות מוגדר־גודל מראש. בניגוד ל־sysread, אינך עושה substr־pad או הקצאה מראש של VAR - shmread משים את התוצאה ישירות.

  • Taint. תחת -T, VAR מוכתם בהצלחה ללא קשר למה שהחזיק לפני. הלבן דרך התאמת קבוצת־לכידה ($data =~ /\A(.*)\z/s and $data = $1) רק לאחר שתיקפת שהבתים בטוחים לפעולה הרגישה שאתה עומד לבצע.

  • לא לכל פלטפורמה יש SysV IPC. במערכות ללא shmat(2) הקריאה נכשלת בזמן ריצה (בדרך כלל ENOSYS); קוד נייד אמור לשמור עם eval או בדיקת תכונה.

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

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

ראו גם#

  • shmwrite - ההפוך: מעתיק מחרוזת לתוך מקטע ב־offset נתון

  • shmget - משיג או יוצר את ID המקטע ש־shmread פועל עליו

  • shmctl - מתשאל מטא־נתוני מקטע (IPC_STAT ממלא shmid_ds שאתה יכול להשתמש בו לבדיקת־גבולות של POS + SIZE) או מסיר את המקטע כשגמרת

  • sysread - האנלוג של file-descriptor; אותה צורת ״בתים לתוך סקלר״, מקור שונה

  • unpack - הופך את הבתים הגולמיים המוחזרים ב־VAR לשדות מטיופסים

  • IPC::SysV - המודול שמספק את IPC_PRIVATE, S_IRUSR, ואת הקבועים האחרים שתעביר ל־shmget