# System V IPC System V IPC נותן לשני תהליכים בלתי־קשורים משאב משותף שהגרעין מחזיק בבעלותו: **מערכת סמפורים** לתיאום, או **מקטע זיכרון משותף** להעברת בתים ללא העתקה דרך pipe. כל משאב מזוהה על־ידי מפתח שלם ושורד עד שתהליך מסיר אותו במפורש. מודולי הנוחות `IPC::SysV`, `IPC::Semaphore` ו־`IPC::SharedMem` אינם זמינים ב־PetaPerl, ולכן המתכונים כאן משתמשים במשפחת הפונקציות המובנות הגולמית [`semget`](../../p5/core/perlfunc/semget.md) / [`shmget`](../../p5/core/perlfunc/shmget.md) עם ערכי הדגלים הכתובים כמספרים פשוטים. פונקציות מובנות אלה הן השכבה שהמודולים עוטפים; שימוש בהן ישירות עולה רק כמה קבועים בעלי שם שאתם מספקים בעצמכם. ## קבועי הדגלים שאתם צריכים מספר מצומצם של שלמים קטנים שולט באופן שבו קריאות אלה מתנהגות. אלה הם ערכי ה־Linux הסטנדרטיים: ```perl use constant { IPC_PRIVATE => 0, # "give me a fresh, private key" IPC_CREAT => 0o1000, # create the resource if absent IPC_EXCL => 0o2000, # fail if it already exists IPC_RMID => 0, # control command: remove the resource }; ``` תשעת הביטים הנמוכים של מילת הדגל הם ביטי הרשאה רגילים, אותם `0600` / `0644` שהייתם מעבירים ל־[`chmod`](../../p5/core/perlfunc/chmod.md). `IPC_CREAT | 0600` פירושו ”צור אותו, קריאה/כתיבה לבעלים“. ## מסירה דרך זיכרון משותף זיכרון משותף הוא הערוץ המהיר ביותר: תהליך אחד כותב בתים לתוך מקטע, אחר קורא אותם ישירות החוצה, ללא העתקת גרעין ביניהם. תכנית זו יוצרת מקטע, כותבת מטען, מבצעת fork, והילד קורא את אותם בתים בחזרה: ```perl use constant { IPC_PRIVATE => 0, IPC_CREAT => 0o1000, IPC_RMID => 0, }; my $size = 1024; my $id = shmget(IPC_PRIVATE, $size, IPC_CREAT | 0600); defined $id or die "shmget: $!"; my $payload = "shared-payload"; shmwrite($id, $payload, 0, length $payload) or die "shmwrite: $!"; my $kid = fork() // die "fork: $!"; if ($kid == 0) { # Child reads the same segment the parent wrote. shmread($id, my $buf, 0, length $payload) or die "shmread: $!"; print "child read: $buf\n"; # child read: shared-payload exit 0; } waitpid($kid, 0); # The segment outlives the processes - remove it explicitly. shmctl($id, IPC_RMID, 0) or warn "shmctl: $!"; ``` שתי נקודות מכריעות אם הקוד הזה דולף: - **`shmread` / `shmwrite` מקבלים אורך מפורש.** הם אינם עוצרים ב־NUL או בתו שורה חדשה; אתם אומרים להם בדיוק כמה בתים להעביר, החל מהיסט. העבירו `length $payload` כך שהקורא והכותב יסכימו על הגודל. - **`IPC_RMID` אינו אוטומטי.** מקטע משותף נשאר בגרעין לאחר שכל תהליך שהיה מחובר אליו יצא. ניתן לראות מקטעים יתומים עם `ipcs -m` ב־shell. תמיד צמדו [`shmget`](../../p5/core/perlfunc/shmget.md) עם [`shmctl`](../../p5/core/perlfunc/shmctl.md) `IPC_RMID` תואם. ## סמפור לתיאום מערכת סמפורים היא מערך קטן של מונים שהגרעין שומר עליהם. השימוש הקלאסי הוא נעילה: תהליך מקטין את המונה כדי להיכנס לקטע קריטי ומגדיל אותו כדי לצאת. מתכון זה יוצר מערכת בעלת איבר אחד, מאתחל אותה, ומסיר אותה: ```perl use constant { IPC_PRIVATE => 0, IPC_CREAT => 0o1000, IPC_RMID => 0, SETVAL => 16, # semctl command: set one value GETVAL => 12, # semctl command: read one value }; # A set with one semaphore. my $sem = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); defined $sem or die "semget: $!"; # Initialise semaphore 0 to the value 1 (one token available). semctl($sem, 0, SETVAL, 1) or die "semctl SETVAL: $!"; my $value = semctl($sem, 0, GETVAL, 0); print "semaphore value: $value\n"; # semaphore value: 1 # Remove the set when finished. semctl($sem, 0, IPC_RMID, 0) or warn "semctl IPC_RMID: $!"; ``` פעולות ההמתנה/סיגנל עצמן עוברות דרך [`semop`](../../p5/core/perlfunc/semop.md), שמקבל מחרוזת ארוזה של שלשות `(sem_num, sem_op, sem_flg)` שנבנו עם [`pack`](../../p5/core/perlfunc/pack.md). הקטנה באחד ממתינה עד שאסימון פנוי; הגדלה באחד משחררת אותו. כמו בזיכרון משותף, מערכת סמפורים שהגרעין מחזיק בבעלותו חייבת להיות מוסרת עם `IPC_RMID` אחרת היא נשארת - גלויה תחת `ipcs -s`. ## קישורים מקושרים להפניה - [`shmget`](../../p5/core/perlfunc/shmget.md) - יצירה או פתיחה של מקטע משותף - [`shmread`](../../p5/core/perlfunc/shmread.md) / [`shmwrite`](../../p5/core/perlfunc/shmwrite.md) - העברת בתים פנימה והחוצה - [`shmctl`](../../p5/core/perlfunc/shmctl.md) - בקרה, כולל `IPC_RMID` - [`semget`](../../p5/core/perlfunc/semget.md) - יצירה או פתיחה של מערכת סמפורים - [`semop`](../../p5/core/perlfunc/semop.md) - פעולות ההמתנה/סיגנל - [`semctl`](../../p5/core/perlfunc/semctl.md) - הגדרה, קריאה והסרה - [`pack`](../../p5/core/perlfunc/pack.md) - בניית מחרוזת הפעולה של `semop` ## הבא זיכרון משותף וסמפורים הם הערוצים כבדי־המשקל. עבור הערוצים הקלים יותר, מוכווני־הזרם, ראו [תהליכי משנה ותהליכים נלווים](subprocesses.md) ו־[סוקטי TCP](sockets-tcp.md).