41
הההההה ההההה ההההה8 – ההההההההההההה-Linux

מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

  • View
    258

  • Download
    0

Embed Size (px)

Citation preview

Page 1: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה

Linux- – סינכרוניזציה ב8תרגול

Page 2: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 2(c) 2003 ארז חדד

תוכן התרגול

-מבוא לסינכרוניזציה בLinux סנכרון בין חוטיPOSIX

mutexcondition variableסמפורים

סינכרון נתונים בגרעיןהוראות אטומיותspin lockssemaphoresחסימת פסיקות

Page 3: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 3(c) 2003 ארז חדד

Linuxמבוא לסינכרוניזציה ב-

)הצורך בסינכרון הקשרי ביצוע שונים )כגון חוטים ותהליכיםהינו חיוני בכל מערכת הפעלה, כפי שראינו בדוגמאות רבות

בהרצאות ותרגוליםLinux מספקת מגוון רחב של מנגנונים לסנכרון בין חוטים ובין

תהליכים, הן כשירות לקוד משתמש והן לצורך שימוש עצמי בספריות ובגרעין

על-מנת להשתמש במנגנון כלשהו, כל החוטים/תהליכיםחייבים לשתף פעולה

לדוגמה: אם חוט לא נועל מנעול בכניסה לקטע הקריטי, לא ניתן למנועמהחוט לבצע את הקטע הקריטי בצורה לא מתואמת

בתרגול זה נציג תחילה את עיקר מנגנוני הסנכרון עבור חוטים( ונסיים בהסבר כללי על סנכרון בתוך APIברמת המשתמש )

הגרעין

Page 4: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 4(c) 2003 ארז חדד

Linux ב-POSIXסנכרון בין חוטי

Linux Threads תומכת בחלק ממנגנוני הסנכרון POSIXהמוגדרים ב-

mutexes, condition variables-תמיכה בmonitors

( סמפוריםPOSIX 1003.1b))אך עבור חוטים בלבד )לא בין תהליכים..

אין תמיכה במנעולי קוראים-כותביםאך ניתן לממש מנעולים כאלה, כפי שנראה בהמשך..

,כזכור מהתרגול הקודםLinux מספקת גם תמיכה System V IPCבסמפורים בין תהליכים דרך

Page 5: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 5(c) 2003 ארז חדד

)mutex )1מנעולי

מנעולmutex מאפשר לחוט אחד בדיוק להחזיק בו )או "לנעול" אותו(

כל חוט אחר המבקש להחזיק במנעול ייחסם עד אשרהמנעול ישוחרר

רק החוט המחזיק במנעול אמור לשחרר אותו )"בעלות" עלהמנעול(

-השימוש המקובל בmutex הוא להגנה על קטע קריטי של קוד ע"י נעילת המנעול בכניסה לקטע הקריטי

ושחרורו בסופו בדרך-כלל מבוצעת הגנה על נתונים משותפים

באמצעות הגדרת הקוד הניגש לנתונים כקטע קריטי

Linux ב-POSIXסנכרון בין חוטי

Page 6: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 6(c) 2003 ארז חדד

)mutex )2מנעולי

פעולות עלmutex:

#include <pthread.h> אתחולmutex:לפני השימוש

int pthread_mutex_init)pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr(;

פינויmutexבתום השימוש

int pthread_mutex_destroy)pthread_mutex_t *mutex(;

-הפעולה נכשלת אם הmutexמאותחל אבל נעול

Linux ב-POSIXסנכרון בין חוטי

Page 7: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 7(c) 2003 ארז חדד

)mutex )3מנעולי

נעילתmutex:int pthread_mutex_lock)pthread_mutex_t *mutex(;

-הפעולה חוסמת עד שהmutexמתפנה ואז נועלת אותו נסיון לנעילתmutex:

int pthread_mutex_trylock)pthread_mutex_t *mutex(;

-הפעולה נכשלת אם הmutexכבר נעול, אחרת נועלת אותו שחרורmutex:נעול

int pthread_mutex_unlock)pthread_mutex_t *mutex(;

Linux ב-POSIXסנכרון בין חוטי

Page 8: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 8(c) 2003 ארז חדד

)mutex )4מנעולי

:פרמטריםmutexהמנעול עליו מבוצעת הפעולה – mutexattr-מגדיר את תכונות ה – mutex

-בLinux Threads-מוגדרת רק תכונת "סוג" ה mutex המתבטאת , בנעילה ובשחרור, כמוצג בשקף הבאmutexבהתנהגות ה-

– ברירת המחדלNULL – mutex"מסוג "מהיר לעבוד עם מומלץ mutex מסוג "בודק שגיאות", כדי למנוע מצבים

בעייתיים כגון אלו המסומנים באדום בשקף הבא-פרטים כיצד לבחור את סוג הmutex-ב man pages

:בהצלחה, ערך אחר בכישלון0ערך מוחזר

Linux ב-POSIXסנכרון בין חוטי

Page 9: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 9(c) 2003 ארז חדד

)mutex )5מנעולי

שחרור מנעול ע"י החוט המחזיק

במנעול

שחרור מנעול ע"י חוט שאינו מחזיק

במנעול

נעילה חוזרת ע"י החוט המחזיק

במנעול

mutexסוג ה-

מהירDEADLOCKmutexמותרמותר

מקטין מונה נעילה . 1עצמית ב-

נשאר mutexה-נעול עד שהמונה

0מגיע ל-

מגדיל מונה נעילה מותר1עצמית ב-

mutexרקורסיבי

בודק mutexכשלוןכשלוןמותרשגיאות

Linux ב-POSIXסנכרון בין חוטי

Page 10: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 10(c) 2003 ארז חדד

)mutex )6מנעולי

pthread_mutex_t m;int count;

void update_count)( {pthread_mutex_lock)&m(;count = count * 5 + 2;pthread_mutex_unlock)&m(;

}

-להלן דוגמה המשתמשת בmutex:

int get_count)( {int c;pthread_mutex_lock)&m(;c = count;pthread_mutex_unlock)&m(;return c;

}

?)(update_count בתוך countמדוע צריך להגן על הגישה ל-1. בעדכונים מחוטים שונים. countכדי למנוע שיבוש ערך

?)(get_count בתוך countמדוע צריך להגן על הגישה ל-2.כדי למנוע קבלת תוצאות חלקיות הנוצרות במהלך העדכון

, לא מובטח שהקוד הנפרש באסמבלר הינו++countשימו לב! גם אם ביטוי ההגדלה היה אטומי, ולכן יש להפעיל מנגנון סנכרון לפי הצורך.

Linux ב-POSIXסנכרון בין חוטי

Page 11: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 11(c) 2003 ארז חדד

(1משתני תנאי )

mutex מאפשר מדיניות סנכרון פשוטה של חוט אחד לכל היותר הניגש לקטע הקריטי בכל זמן נתון

ניתן לממש סנכרון מורכב יותר בכל מיני שיטות על-מנת לממש בצורה מובנית אובייקט סנכרון מכל סוג

conditionשהוא, משתמשים במשתני תנאי )variables)

משתנה תנאי מאפשר לחוט להמתין לכל ארוע שהואהמוגדר ע"י המתכנת

-משתנה תנאי תמיד קשור לmutexמסוים mutex + 0 = או יותר משתני תנאי monitor

Linux ב-POSIXסנכרון בין חוטי

Page 12: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 12(c) 2003 ארז חדד

(2משתני תנאי )

פעולות על משתני תנאי#include <pthread.h>

:איתחול משתנה תנאי לפני השימושint pthread_cond_init)pthread_cond_t *cond,

pthread_condattr_t *cond_attr(;:פינוי משתנה תנאי בסיום השימוש

int pthread_cond_destroy)pthread_cond_t *cond(; הפעולה נכשלת אם יש חוטים הממתינים על משתנה

התנאי

Linux ב-POSIXסנכרון בין חוטי

Page 13: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 13(c) 2003 ארז חדד

(3משתני תנאי )

:המתנה על משתנה תנאיint pthread_cond_wait)pthread_cond_t *cond,

pthread_mutex_t *mutex(; החוט הממתין חייב להחזיק במנעולmutexלפני הקריאה פעולה אטומית: משחררת את המנעולmutex ומעבירה את

החוט להמתין על משתנה התנאי:שחרור חוט ממתין על משתנה תנאי

int pthread_cond_signal)pthread_cond_t *cond(; אם אין חוט שממתין כרגע על משתנה התנאיcond –

הפעולה חסרת השפעה )ואינה נזכרת הלאה(

Linux ב-POSIXסנכרון בין חוטי

Page 14: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 14(c) 2003 ארז חדד

(4משתני תנאי ) אם קיימים חוטים ממתינים על משתנה התנאיcond –

מפסיק )הגינות לא מובטחת( החוטים הממתינים אחדלהמתין על משתנה התנאי, ויחזור לפעילות )יעבור את

( לאחר שינעל מחדש את )(pthread_cond_waitה-(Mesa )סגנון mutexה-

:שחרור כל החוטים הממתינים על משתנה תנאיint pthread_cond_broadcast)pthread_cond_t

*cond(; אם אין חוט שממתין כרגע על משתנה התנאיcond –

הפעולה חסרת השפעה )ואינה נזכרת הלאה( אם קיימים חוטים ממתינים על משתנה התנאיcond – כל

החוטים הממתינים מפסיקים להמתין על משתנה התנאי, ויחזרו לפעילות בזה אחר זה )בסדר כלשהו, לאו דוקא הוגן(

mutexלאחר שינעלו מחדש את ה-

Linux ב-POSIXסנכרון בין חוטי

Page 15: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 15(c) 2003 ארז חדד

(5משתני תנאי )

:פרמטריםcondמשתנה התנאי עליו מבוצעת הפעולה – cond_attrמגדיר את תכונות משתנה התנאי –

-בLinux Threads אין משמעות לפרמטר זה. ערך NULL

mutex המנעול אליו משויך משתנה התנאי בביצוע – pthread_cond_wait)(

:בהצלחה, ערך אחר בכישלון0ערך מוחזר הפונקציותinit, signal, broadcast, wait תמיד מחזירות

ערך הצלחה

Linux ב-POSIXסנכרון בין חוטי

Page 16: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 16(c) 2003 ארז חדד

(1קישור בין אירוע ומשתנה תנאי )

הדרך הפשוטה ביותר לקשר בין אירוע המציין קיוםמצב רצוי כלשהו למשתנה תנאי היא בקוד כדלקמן:

אצל הממתין לאירוע )החוט שרוצה להתקדם רק כאשריושג המצב הרצוי(:

if <לא מתקיים המצב הרצוי>pthread_cond_wait)< מנעול>, <משתנה התנאי >(;

<המשך הקוד> אצל יוצר האירוע )החוט שיוצר את המצב הרצוי ומסמן

לחוטים הממתינים להתקדם(:if < אם זה ודאי >מתקיים המצב הרצוי ifאפשר לוותר על ה-

pthread_cond_signal)<משתנה התנאי>(;!בשקף הבא(אבל.. בעיה(

Page 17: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 17(c) 2003 ארז חדד

(2קישור בין אירוע ומשתנה תנאי )

פעולתsignalלא מאפשרת לחוט הממתין להמשיך מיד -החוט הממתין צריך תחילה לנעול את הmutex מחדש )סגנון

Mesa)-לכן, ייתכן שלפני שהחוט הממתין ינעל את הmutex

מחדש יספיק להכנס חוט נוסף שישנה את הנתונים כך שהמצב הרצוי כבר לא מתקיים

במימוש לפי סגנוןHoare נדיר מאוד(, החוט שמבצע( signal גם מוותר על המנעול ומעביר אותו לחוט הממתין, כך שאם

הנתונים מוגנים ע"י המנעול, מצבם אינו יכול להשתנות והחוט הממתין יכול להמשיך ללא הפרעה במצב הרצוי.

מצד שני, בסגנוןHoare החוט שביצע signal נענש" על כך" שסייע לחוט אחר להתקדם בכך שהוא מוכרח לוותר על

ההתקדמות שלו עצמו ולעבור להמתין על המנעול עד שישוחרר

Page 18: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 18(c) 2003 ארז חדד

(3קישור בין אירוע ומשתנה תנאי )

דוגמה מההרצאה – מימוש תורpthread_mutex_t qlock;pthread_cond_t notEmpty;/* … initialization code … */

void enqueue)item x( {pthread_mutex_lock)&qlock(;/* … add x to queue … */pthread_cond_signal)&notEmpty(;pthread_mutex_unlock)&qlock(;

}

item dequeue)( {pthread_mutex_lock)&qlock(;if <stack is empty> pthread_cond_wait)&notEmpty,

&qlock(;/* … remove item from queue … */pthread_mutex_unlock)&qlock(;/* .. return removed item */

}

Page 19: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 19(c) 2003 ארז חדד

(4קישור בין אירוע ומשתנה תנאי )

נניח, לפי הדוגמה שהתור ריק וחוטt1-קורא ל dequeue)( ולכן ,ממתין

כעת חוטt2-קורא ל enqueue)( מכניס איבר לתור ומבצע ,signal

חוטt1עובר להמתין לשחרור המנעול כעת מגיע חוטt3-וקורא ל ,dequeue)(

חוטt3נחסם בהמתנה למנעול בתחילת הקוד חוטt2 משחרר את המנעול ומסיים את enqueue)( חוטt3מקבל את המנעול, נכנס, מוציא איבר ומסיים חוטt1 ומנסה מקבל את המנעול, ממשיך לבצע את הקוד

להוציא איבר מתור ריק!

Page 20: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 20(c) 2003 ארז חדד

(5קישור בין אירוע ומשתנה תנאי )

?ממה נבעה הבעיה בדוגמה-מכך שהתנאי של האירוע לא נבדק אחרי הwait

?כיצד ניתן לפתור את הבעיה:ע"י בדיקה חוזרת של תנאי האירוע והמתנה נוספת לפי הצורך. לדוגמה

while <stack is empty>pthread_cond_wait)…(

האם הבעיה יכלה לקרות גם אם המנעול היה הוגן )תורFIFO?)

כן! אםt3-היה קורא ל dequeue)(-ומחכה למנעול לפני ש t2 הגיע signalל-

-האם הבעיה יכלה לקרות אם הmonitor היה בסגנון Hoare? לא! כיt1 היה מקבל את המנעול לפני t3

Page 21: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 21(c) 2003 ארז חדד

(1בעיית הקוראים-כותבים )

:בעית הקוראים-כותבים תזכורת מההרצאה מתארת מצב נפוץ בו קיים משאב עבורו מוגדרות שתי פעולות: "קריאה" ו"כתיבה"

מספר חוטים קוראים יכולים לגשת למשאבבו-זמנית

חוט כותב זקוק לגישה בלעדית למשאב בשקפים הבאים נדגים כיצד ניתן לממש מנגנון

monitorסנכרון שכזה באמצעות

Linux ב-POSIXסנכרון בין חוטי

Page 22: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 22(c) 2003 ארז חדד

(2בעיית הקוראים-כותבים ):הגדרת המנגנון

#include <pthread.h>int number_of_readers;pthread_cond_t readers_condition;

int number of writers;pthread_cond_t writers_condition;mutex_t global_lock;

void readers_writers_init)( {number_of_readers = 0;pthread_cond_init)&readers_condition, NULL(;number_of_writers = 0;pthread_cond_init)&writers_condition, NULL(;pthread_mutex_init)&global_lock, NULL(;

}

מספר החוטים שקוראים מהמשאב

מספר החוטים שכותבים למשאב

אירוע: מותר לקרוא

אירוע: מותר לכתוב

Linux ב-POSIXסנכרון בין חוטי

Page 23: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 23(c) 2003 ארז חדד

(3בעיית הקוראים-כותבים )

void reader_lock)( {pthread_mutex_lock)&global_lock(;while )number_of_writers > 0(

pthread_cond_wait)&readers_condition, &global_lock(;number_of_readers++;pthread_mutex_unlock)&global_lock(;

}<Read Data>void readers_unlock)( {

pthread_mutex_lock)&global_lock(;number_of_readers--;if )number_of_readers == 0(

pthread_cond_signal)&writers_condition(;pthread_mutex_unlock)&global_lock(;

}

Linux ב-POSIXסנכרון בין חוטי

waitצריך לבדוק את תנאי הבדיקה גם לאחר

Page 24: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 24(c) 2003 ארז חדד

(4בעיית הקוראים-כותבים )void write_lock)( {

pthread_mutex_lock)&global_lock(;while ))number_of_writers > 0( || )number_of_readers > 0((

pthread_cond_wait)&writers_condition, &global_lock(;number_of_writers++;pthread_mutex_unlock)&global_lock(;

}<Write Data>void write_unlock)( {

pthread_mutex_lock)&global_lock(;number_of_writers--;if )number_of_writers == 0( {

pthread_cond_broadcast)&readers_condition(;pthread_cond_signal)&writers_condition(;

}pthread_mutex_unlock)&global_lock(;

}

..ifלמעשה, אין צורך ב-

עדיפות לקוראים ממתיניםעל-פני כותבים ממתינים

Linux ב-POSIXסנכרון בין חוטי

צריך לבדוק את תנאי הבדיקה גם

waitלאחר

Page 25: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 25(c) 2003 ארז חדד

(1סמפורים )

Linux Threadsתומכת בסמפורים כלליים :תזכורת מההרצאה

:בסמפור מוגדרות שתי פעולות בסיסיותwait-ו post-בהרצאה קראנו לpost בשם signal אך כאן נימנע משם זה כדי לא ,

של משתנה תנאיsignalלבלבל עם פעולת מונהלסמפור יש .wait מורידה את ערך המונה

מעלה אותוpostופעולת -פעולת 0כאשר מונה הסמפור אינו גדול מ ,wait חוסמת

ויעלה postאת החוט הקורא עד שחוט אחר כלשהו יבצע 0את ערך המונה מעל

Linux ב-POSIXסנכרון בין חוטי

Page 26: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 26(c) 2003 ארז חדד

(2סמפורים )

ניתן להתייחס לסמפור כאל מאגר של מספר יחידות שלמשאב

פעולתwait .ממתינה עד שיש יחידה פנויה ואז "צורכת" אותה מחזירה יחידה למאגר בתום השימושpostפעולת

כפי שראינו בהרצאה, ניתן לפתור עם סמפורים את בעייתהיצרן-צרכן

סמפור בינארי(, 1אם סמפור מאותחל עם מונה בערך( ניתן להשתמש בו על-מנת להגן על קטע קריטי )ליצור

מניעה הדדית בין החוטים הניגשים( עם זאת, סמפור בינארי אינו מנעולmutex משום שכל חוט יכול ,

על הסמפור קודם לכן wait על סמפור, גם אם לא ביצע postלבצע )אין "בעלות" על הסמפור(

Linux ב-POSIXסנכרון בין חוטי

Page 27: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 27(c) 2003 ארז חדד

(3סמפורים )

-סמפור ממומש בLinux Threads בקירוב כפי שהודגם בהרצאה:

לכל סמפור יש מונה, תור ומנעול שתפקידו להגן על הקודפעולות אטומיות(של הפעולות של הסמפור )

פעולתwait-1, מקטינה אותו ב-0: אם המונה גדול מ ,אחרת החוט נכנס להמתנה בתור

פעולתpost אם תור הממתינים לא ריק, מוציאה ומעירה :1את החוט הראשון בתור, אחרת מגדילה את המונה ב-

( תור הממתינים הוגןFIFO עד כדי עדיפות, כלומר חוט )בעדיפות גבוהה יצא מהתור לפני חוט בעדיפות נמוכה

Linux ב-POSIXסנכרון בין חוטי

Page 28: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 28(c) 2003 ארז חדד

(4סמפורים )

:פעולות על סמפורים#include <semaphore.h>

לא לשכוח לקשר לספרייהpthread!:אתחול סמפור לפני השימוש

int sem_init)sem_t *sem, int pshared, unsigned int value(;

:פינוי סמפור בתום השימושint sem_destroy)sem_t *sem(;

Linux ב-POSIXסנכרון בין חוטי

Page 29: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 29(c) 2003 ארז חדד

(5סמפורים )

ביצועwait:על סמפור int sem_wait)sem_t *sem(;

ביצועpost:על סמפור int sem_post)sem_t *sem(;

גרסה לא-חוסמת שלwait:int sem_trywait)sem_t *sem(;

-חוזרת מיד ונכשלת0אם המונה של הסמפור אינו גדול מ ,:קריאת ערך מונה הסמפור

int sem_getvalue)sem_t *sem, int *sval(;

Linux ב-POSIXסנכרון בין חוטי

Page 30: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 30(c) 2003 ארז חדד

(6סמפורים )

:פרמטריםsemהסמפור עליו מבוצעות הפעולות – pshared-מציין שהסמפור יכול להיות 0 – אם ערכו גדול מ ,

משותף למספר תהליכים. תכונה זו אינה נתמכת, ולכן נציב קבוע0בו

valueערכו ההתחלתי של מונה הסמפור – svalמצביע למקום בו יאוחסן ערך מונה הסמפור –

:( בכישלון1 בהצלחה, )0ערך מוחזר- הפונקציותsem_wait)(-ו sem_getvalue)(תמיד מצליחות

Linux ב-POSIXסנכרון בין חוטי

Page 31: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 31(c) 2003 ארז חדד

סמפורים – שאלת דוגמה ממבחן

:נתונה הסדרה הבאההאיברים נתונים וגלובליים בתהליך יש לחשב את ע"יn חוטים בתהליך, כך שהחוט

יחשב את האיבר iה- הראו כי ניתן לממש את החישוב ע"י סמפורים

הוא ריבוע מספר שלם( nכלליים )הניחו כי ציינו את איתחול הסמפורים ופעולות החוטים על

הסמפורים

}1,|{ 21 naaaa nnnn

10 ,aa

na

ia

n2

Linux ב-POSIXסנכרון בין חוטי

Page 32: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 32(c) 2003 ארז חדד

סמפורים – פתרון שאלת הדוגמה

בהנחה ש- כאשרA>1 הוא מספר שלם כלשהו, נסדר את החוטים בריבוע

לכל חוט במטריצה יש אינדקס שורה ועמודה נחזיק סמפור אחד לכל עמודה, בסימון:כנ"ל סמפור לכל שורה:סמפור מאותחל ל-אתחול A סמפור מאותחל ,

0 ושאר הסמפורים מאותחלים ל-1ל-:השלימו לבדחישוב ?היכן ממוקמת המטריצה הנ"ל

2AnAA

110 ,...,, ACCC

110 ,...,, ARRR0R0C

Linux ב-POSIXסנכרון בין חוטי

Page 33: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 33(c) 2003 ארז חדד

)Linux )1סינכרוניזציה בתוך גרעין

"ניתן לראות את גרעין מערכת ההפעלה כ"שרתהמקבל "בקשות" בצורת פסיקות מהתקן חומרה

חיצוני או מתוכנה פנימית בעקבות כל "בקשה" הגרעין מבצע רצף של קוד

המטפל בבקשה. רצף קוד זה נקרא מסלול בקרה (Kernel Control Pathבגרעין )

לדוגמה: טיפול בקריאת מערכת מסוימת של תהליך מסוים )(system_callהוא מסלול בקרה שכזה המתחיל בפונקציה

, כפי שראינו בתרגולים )(ret_from_sys_callומסתיים ב-קודמים

למסלול בקרה איןdescriptor כי הוא לא חוט או תהליך – זהו פשוט מסלול ביצוע הוראות בתוך הגרעין

Page 34: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 34(c) 2003 ארז חדד

)Linux )2סינכרוניזציה בתוך גרעין המעבד יכול למתג בין מספר מסלולי בקרה בתוך

הגרעין בעקבות תסריט כגון:מתבצעת החלפת הקשר בין תהליכים בגרעין במהלך ביצוע מסלול בקרה לאחר פסיקה כלשהי, קורית

פסיקה נוספת המחייבת תחילת ביצוע מסלול בקרה נוסף כמו כן, במערכת מרובת מעבדים, מספר מסלולי

בקרה מתבצעים במקביל בגרעין לפיכך, מבני הנתונים בגרעין עלולים להשתבש

כתוצאה מגישה לא מתואמת ממספר מסלולי בקרה שונים ולכן יש להגן עליהם

גישה לא מתואמת ממספר מקומות יוצרת( מירוץrace) – מצב שבו הנתונים עלולים להגיע למצב לא תקין במהלך

הביצוע, כגון ערכים שגויים, מצביעים למקומות לא מתאימים וכו'.

Page 35: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 35(c) 2003 ארז חדד

)Linux )3סינכרוניזציה בתוך גרעין

:ישנם גורמים שמפשטים מעט את הבעיה גרעיןLinux הוא non-preemptive כלומר תהליך הנמצא ,

יוותר על המעבד רק מרצונו שלו )קריאה kernel modeב-( ולא מאילוץ של המערכת)(scheduleל-

אם מסלול בקרה של תהליך נקטע ע"י מסלול בקרה שלטיפול בפסיקה, מסלול הבקרה של התהליך ימשיך לאחר

סיום הטיפול בפסיקהמסלולי בקרה מתבצעים בצורה מקוננת

מסלול בקרה של טיפול בפסיקה שאינה קריאת מערכתאינו יכול להקטע ע"י מסלול בקרה של טיפול בקריאת

מערכת

Page 36: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 36(c) 2003 ארז חדד

)Linux )4סינכרוניזציה בתוך גרעין

לפיכך, במערכת עם מעבד יחיד, למשל, קריאתמערכת שאינה חוסמת מתבצעת בצורה אטומית ביחס לקריאות מערכת אחרות, כך שאם היא לא

משתמשת במבני נתונים הנגישים ממסלולי בקרה של פסיקות אחרות, היא יכולה לגשת לנתונים בבטחה

עם זאת, קריאת מערכת שחוסמת )מוותרת עלהמעבד( חייבת להשאיר את מבני הנתונים בגרעין תקינים לפני שתוותר על המעבד, ובחזרה לביצוע חייבת לבדוק שהנתונים לא שונו ע"י מסלול בקרה

אחר לעדכן את גודל החוצץוגםלמשל: להוסיף נתונים לחוצץ

וכמובן, קריאות מערכת אינן אטומיות לעולם..במערכת מרובת מעבדים – סיבוך נוסף..

Page 37: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 37(c) 2003 ארז חדד

)Linux )5סינכרוניזציה בתוך גרעין

סנכרון גישה לנתונים ממסלולי בקרה שונים מבוצע באמצעותקטעים קריטיים בגרעין

קטע קריטי בגרעין הוא קטע קוד שחייב להתבצע בשלמותו ע"י מסלולהבקרה שנכנס אליו לפני שכל מסלול בקרה אחר יוכל להכנס לקטע זה

:ההגנה על קטעים קריטיים מבוצעת במגוון אמצעים כגון( הוראות אטומיותAtomic Operations( פעולות עדכון נתונים :)Read-

Modify-Write המבוצעות באופן אטומי ברמת המכונה ביחס לכל )המעבדים

הקטע הקריטי מוכל בהוראה האטומית הוראות אטומיות מנצלות תמיכה של החומרה, כגון הוראתlock )IA32(

( עד memory busהנועלת את ערוץ הגישה של כל המעבדים לזיכרון )לסיום ההוראה שאחריה

:דוגמה להוראה אטומיתtest_and_set_bit)( המדליקה ביט ומחזירה את ,ערכו הקודם

Page 38: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 38(c) 2003 ארז חדד

)Linux )6סינכרוניזציה בתוך גרעין

Spin Locks-למעשה, מנעול הממומש כ :busy wait קיים רק במערכת מרובת מעבדים, מפני שאילולי כן, במערכת מעבד יחיד

נעול, והיה עלול להמתין לנצח – כי spin lockמסלול בקרה היה נתקל ב-המסלול שהחזיק את המנעול נקטע ואינו יכול לחזור לרוץ עד שהממתין

יסיים ,למעשהbusy wait הוא המתנה יעילה כאשר מדובר בנעילות קצרות מאוד

כפי שקורה בגרעין, מפני שאין את התקורה של של כניסה ויציאה מהמתנה טיפוסspinlock_t בקובץ גרעין include/linux/spinlock.h :קיימת גרסה נוספתread-write spin locks טיפוס( rwlock_t המממשת )

busy waitמנעולי קוראים-כותבים ב- סמפורים כלליים: מימוש נפרד המיועד לשימוש פנימי בגרעין בלבד

.המתנה של מסלול בקרה לסמפור גורמת להמתנת התהליך שרץ כרגעלכן, סמפורים משמשים בקריאות מערכת ואינם משמשים בטיפול

בפסיקות אחרות )אחרת תהליך נכנס להמתנה מסיבה שאינה תלויה בו( טיפוסstruct semaphore בקובץ גרעין include/asm-i386/semaphore.h

Page 39: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 39(c) 2003 ארז חדד

)Linux )7סינכרוניזציה בתוך גרעין

( חסימת פסיקות מקומיתLocal Interrupt Disabling :)חסימת הפסיקות במעבד הנוכחי בו מתבצע מסלול

הבקרה אחד האמצעים החשובים ביותר להגנה על קטע קריטי – מאפשר

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

חסימת הפסיקות לזמן רב עלולה לגרום לפגיעה בביצועים ולאבדןפסיקות חיוניות

אמצעי זה אינו מספיק במערכות מרובות מעבדים, שם בד"כspin locksמשלבים אותו עם

,בסיום הקטע הקריטי משוחזר ערך דגל הפסיקות מלפני כיבויומפני שהדגל לא דלק בהכרח לפני הכיבוי. להלן רצף אופייני

)הפעולות הן מאקרו(:

Page 40: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 40(c) 2003 ארז חדד

)Linux )8סינכרוניזציה בתוך גרעין

__save_flags)old(; __cli)(; /* clear interrupt flag )IF( */<critical section>__resotre_flags)old(;

כל המאקרו שצוינו נמצאים בקובץ הגרעיןinclude/asm-i386/system.h המאקרו__cli)(-ו __sti)( מכילים קריאות להוראות המכונה cli-ו sti

(IFהמבצעות, בהתאמה, חסימה ואפשור של דגל הפסיקות במעבד ) מאקרו אלה נקראים כיום גםlocal_irq_disable)(-ו local_irq_enable)(

( קיימת גם חסימת פסיקות בכל המעבדיםGlobal Interrupt Disabling (, שהיא בשימוש נדיר מאוד )כגון לאיתחול התקני

חומרה מסוימים( הגדרת המאקרו באותו קובץ גרעין כמו בחסימה מקומית עם אותם

שמות מאקרו אך ללא תחילית "__"

Page 41: מערכות הפעלה תרגול 8 – סינכרוניזציה ב-Linux. מערכות הפעלה - תרגול 82 (c) ארז חדד 2003 תוכן התרגול מבוא לסינכרוניזציה

מערכות הפעלה - תרגול 8 41(c) 2003 ארז חדד

)Linux )9סינכרוניזציה בתוך גרעין

:דוגמאות לשימוש במנגנון סנכרון( מונה שימוש במשאבreference counters מוגדל כאשר )

תהליך מקבל את המשאב לשימוש ומוקטן כאשר התהליך מסיים להשתמש במשאב. מכיוון שמשאבים יכולים להיות בשימוש ע"י מספר תהליכים, מתבצעות פעולות ההגדלה

וההקטנה כהוראות אטומיות מבני נתונים שנגישים ממסלולי בקרה של פסיקות שונות

spin lockמוגנים בשילוב של חסימת פסיקות מקומית + חסימת הפסיקות המקומית דרושה על-מנת למנוע מסלולי בקרה

אחרים באותו מעבד מלהכנס לקטע הקריטי-כפי שהוסבר קודם, סמפור וspin lockלא מתאימים למטרה זו

-הspin lock דרוש על-מנת למנוע ממסלולי בקרה במעבדים אחרים מלהכנס לקטע הקריטי, מבלי לחסום פסיקות בכולם לחלוטין