SysV IPC

semctl#

ביצוע פעולת בקרה על מערכת סמפורים של System V.

semctl הוא הקישור ברמת Perl לקריאת המערכת semctl(2). הוא קורא או מתקן את מצבה של מערכת הסמפורים המזוהה על־ידי ID - קבלה או קביעה של ערך של סמפור יחיד, שליפה או התקנה של וקטור הערכים המלא, קריאה של מטא־דאטת semid_ds הקשורה, או הסרת המערכת לחלוטין. CMD בוחר את הפעולה; SEMNUM בוחר איזה סמפור בתוך המערכת (מתעלמים ממנו עבור פקודות לכל־המערכת כמו IPC_STAT, IPC_RMID, GETALL, SETALL); ARG הוא ה־buffer של הקלט או הפלט של הפקודה.

semctl היא עטיפה דקה - הסמנטיקה, קבועי הפקודה, וצורת ARG באים כולם ישירות מהקריאה ברמת C. כמעט תמיד תרצו:

use IPC::SysV;

קודם, למשוך את הקבועים IPC_STAT, IPC_RMID, GETVAL, SETVAL, GETALL, SETALL, GETPID, GETNCNT, GETZCNT.

תקציר#

semctl $id, $semnum, $cmd, $arg
semctl $id, 0,       IPC_RMID, 0            # destroy set
semctl $id, $n,      SETVAL,   $value       # set one
semctl $id, 0,       SETALL,   $packed      # set all

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

ההחזרה עוקבת אחר אותה מוסכמה כמו ioctl:

  • undef בשגיאה (עם $! שנקבע).

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

  • ערך ההחזרה השלם בפועל אחרת.

הבדיקה האידיומטית היא לפיכך:

my $rc = semctl($id, $n, GETVAL, 0);
defined $rc or die "semctl: $!";

יש לבדוק defined, לא אמת - ערך סמפור אפס לגיטימי היה נכשל ב־if ($rc) פשוט.

עבור ערכי CMD שקוראים נתונים לתוך ARG (IPC_STAT, GETALL), ARG חייב להיות lvalue הניתן לשינוי (משתנה פשוט, לא ליטרל או ביטוי); בהצלחה ה־buffer נדרס במקום עם הבתים המוחזרים ומבצעים unpack בעצמכם.

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

קובע את $! בכישלון. אין משתנים גלובליים אחרים של המפענח מעורבים.

דוגמאות#

קריאת הערך הנוכחי של סמפור יחיד:

use IPC::SysV qw(GETVAL);
my $value = semctl($id, $semnum, GETVAL, 0);
defined $value or die "GETVAL: $!";

קביעת סמפור יחיד:

use IPC::SysV qw(SETVAL);
semctl($id, $semnum, SETVAL, 1)
    or die "SETVAL: $!";

קריאת כל ערכי הסמפורים בבת־אחת. ה־buffer חייב להיות מוקצה מראש לגודל הנכון - nsems של shorts מקומיים - לפני הקריאה. pack עם ספירה לא־בשימוש הוא הדרך הרגילה:

use IPC::SysV qw(GETALL);
my $nsems = 4;
my $buf   = pack("s!*", (0) x $nsems);      # allocate room
semctl($id, 0, GETALL, $buf) or die $!;
my @vals = unpack("s!*", $buf);

התקנת מערכת ערכים מלאה:

use IPC::SysV qw(SETALL);
my $buf = pack("s!*", 1, 0, 0, 1);
semctl($id, 0, SETALL, $buf)
    or die "SETALL: $!";

שליפת מבנה semid_ds עבור המערכת. ARG נכתב במקום עם ה־struct הארוז; הפריסה שלו ספציפית־לפלטפורמה, ולכן יש לבצע unpack בעזרת IPC::Semaphore ולא ביד אלא אם מוכרחים:

use IPC::SysV qw(IPC_STAT);
my $ds = "";
semctl($id, 0, IPC_STAT, $ds)
    or die "IPC_STAT: $!";

השמדת מערכת הסמפורים. SEMNUM ו־ARG אינם בשימוש; יש להעביר 0:

use IPC::SysV qw(IPC_RMID);
semctl($id, 0, IPC_RMID, 0)
    or die "IPC_RMID: $!";

מקרי קצה#

  • ARG חייב להיות משתנה אמיתי עבור פקודות קריאה. GETALL ו־IPC_STAT כותבים לתוך ARG; העברת ליטרל (semctl($id, 0, GETALL, "")) או ביטוי קריאה־בלבד היא שגיאת זמן ריצה. תוכן המשתנה הקיים נדרס, לא מתווסף אליו.

  • ל־ARG חייב להיות גודל מראש. הקרנל כותב בדיוק nsems * sizeof(short) בתים עבור GETALL, או sizeof(struct semid_ds) עבור IPC_STAT. העברת buffer קצר יותר היא התנהגות בלתי־מוגדרת בקריאת ה־C הבסיסית; pack("s!*", (0) x $nsems) הוא האידיום הסטנדרטי ל־GETALL.

  • short מקומי, לא short נייד. ערכי סמפור הם C short (חתום, בדרך־כלל 16־ביט). יש להשתמש ב־s! ב־pack / unpack - ה־! בוחר את הסוג המקומי לפלטפורמה. s פשוט מאלץ little-endian 16־ביט ויפיק תוצאות שגויות במערכות big-endian או LP64-short.

  • החזרות "0 but true". GETVAL על סמפור שערכו 0, GETPID/GETNCNT/GETZCNT המחזירים אפס, והצלחות אחרות בעלות ערך אפס - כולן מחזירות את המחרוזת הליטרלית "0 but true". הקשרים אריתמטיים רואים 0; הקשרים בוליאניים רואים אמת. יש להשתמש ב־defined כדי לבדוק כישלון.

  • מתעלמים מ־SEMNUM עבור פקודות לכל־המערכת. IPC_STAT, IPC_RMID, SETALL, GETALL פועלים על כל המערכת. יש להעביר 0 כמוסכמה; העברת כל ערך אחר אינה מזיקה אך מטשטשת כוונה.

  • לאחר IPC_RMID ה־id אינו תקף. כל semctl או semop עוקב על $id נכשל עם EINVAL / EIDRM. אין לשמור את ה־id במטמון מעבר להסרה.

  • המערכת היא קרנל־גלובלית ושורדת מעבר ליציאות תהליכים. מערכת שנוצרה על־ידי סקריפט שקרס נשארת עד שמישהו קורא ל־IPC_RMID (או שהמערכת מבוצעת reboot). יש להשתמש ב־ipcs -s / ipcrm -s מה־shell כדי לבחון או לנקות מערכות שדלפו.

  • הרשאות באות מ־semget. ה־IPC_CREAT | mode שמועבר בזמן יצירה שולט במי רשאי להוציא איזה פקודות semctl. EACCES מ־semctl משמעו שביטי ה־mode אינם מתירים את הפעולה המבוקשת עבור ה־uid האפקטיבי הנוכחי.

הבדלים מ־upstream#

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

ראו גם#

  • semget - יצירה או חיפוש של מערכת הסמפורים שאת ה־id שלה מעבירים ל־semctl

  • semop - פעולות ההמתנה / סיגנל בפועל; semctl לבקרה ובחינה, semop עושה את העבודה

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

  • shmctl - קריאת הבקרה המקבילה עבור זיכרון משותף של System V; אותה מוסכמת ערך־החזרה

  • pack - כיצד לבנות את ה־buffer של ARG עם s! עבור ערכי סמפור ו־struct של semid_ds

  • IPC::Semaphore - עטיפת עצם שמסתירה את semctl מאחורי מתודות בעלות שם; יש לפנות אליה כאשר סקריפט עושה יותר מקריאה אחת או שתיים