שאלה 1 - Elad Aigner

‫מערכות הפעלה ‪2015‬‬
‫סמסטר ב׳‬
‫פתרון מבחן דוגמא‬
‫אוניברסיטת אריאל‬
‫המחלקה למדעי המחשב ומתמטיקה‬
‫ד״ר אלעד חורב‬
‫שאלה ‪:1‬‬
‫א‪ Event .‬הינו מקרה פרטי של ‪ Condition variable‬וניתן לדמותו באמצעות ‪.condition variable‬‬
‫אכן לא כל השפות מבחינות בין שני המנגנונים‪ .‬ההבדל המרכזי הוא בשימוש של שניהם‪ .‬על‬
‫מנת להשהות תהליך או ‪ Thread‬עד אשר אירוע כלשהוא יתרחש מבלי זה יכנס ל ‪critical‬‬
‫‪ section‬נשתמש ב ‪ .Event‬ב ‪ condition variables‬נשתמש אם לאחר האירוע נרצה להיכנס ל‬
‫‪.critical section‬‬
‫ב‪ .‬אלגוריתם ‪ Round Robin‬הינו אלגוריתם לתזמון תהליכים‪ .‬האלגוריתם מתחזק רשימה של‬
‫תהליכים להרצה‪ .‬הפעולה הבסיסית היא להעניק ‪ q‬יחידות זמן ריצה לתהליך שבראש‬
‫הרשימה‪ .‬לאחר ‪ q‬יחידות זמן אלו אם התהליך שרץ זה עתה סיים אזי זה מפונה מן‬
‫הרשימה‪ .‬אחרת מוסף לסוף הרשימה‪ .‬תהליכים חדשים מוספים בסוף הרשימה‪.‬‬
‫היתרון המרכזי הינו שהאלגוריתם הינו ‪ preemptive‬ובעל היכולת לספק הבטחה לכל תהליך‬
‫כי זה לא ירעב לקבלת ‪ .CPU‬החסרון המרכזי הינו הצורך לקבוע את ‪ q‬באופן שזה לא גדול‬
‫מדי מכדי להשפיע לרעה על פרמטרים כגון ‪ turnaround time, waiting time‬וכיו״ב‪ ,‬ומצד שני‬
‫לא קרוב מדי לזמן הדרוש לביצוע ‪ switch‬בין תהליכים מה שיוביל לחוסר ניצול של ה ‪.CPU‬‬
‫‪1‬‬
:‫ להלן הצעה לפתרון‬.‫ג‬
Shared binarySemaphores arrival:=1, departure:=0
Shared integer counter:=0
void join_barrier()
{
down(arrival)
counter=counter+1
if (counter<n):
up(arrival)
else:
up(departure)
down(departure)
counter=counter-1
if (counter > 0):
up(departure)
else:
up(arrival)
}
:‫להלן התשובות‬
.‫ נכון‬.1.‫ד‬
:n = 2 ‫ להלן תרחיש אפשרי עבור‬.‫ לא נכון‬.2.‫ד‬
.while(num[A] > num[B]) ‫ תקוע ב‬A ‫ ותהליך‬CS ‫ בתוך ה‬B ‫( תהליך‬1
.num[A]>num[B] ‫עדיין מתקיים‬.num[B] =0 ‫ וקובע‬CS ‫ יוצא מן ה‬B ‫( תהליך‬2
.‫ לנצח‬remainder code ‫ נשאר ב‬B ‫( תהליך‬3
.num[A] > num[B] = 0 ‫( לנצח מתקיים‬4
2
.‫ד‬
‫שאלה ‪:2‬‬
‫סעיף א‪:‬‬
‫טענה‪ :‬האלגוריתם המוצע מספק ‪.mutual exclusion‬‬
‫הוכחה‪ :‬נניח בשלילה כי הטענה איננה נכונה וכי קיימים זוג תהליכים ‪ A‬ו ‪ B‬אשר נמצאים ב‬
‫‪ CS‬באותו הזמן‪ .‬יהיו ‪ num_A‬ו ‪ num_B‬המספרים שאלו מחזיקים בהם בעת כניסתם ל ‪.CS‬‬
‫בלי הגבלת הכלליות נניח כי‪:‬‬
‫)‪.(*) (num_A,A) < (num_B,B‬‬
‫נשקול את תהליך ‪ .B‬תהליך זה הצליח להיכנס ל ‪ CS‬היות והתרחשו האירועים הבאים‪:‬‬
‫‪.1‬‬
‫‪ B‬קרא ‪ flag[A] = false‬ב ‪ while‬הראשון‪.‬‬
‫‪.2‬‬
‫אחד משני האירועים הבאים התרחש‪:‬‬
‫‪ B .2.1‬קרא ‪ num[A] = 0‬ב ‪ while‬שני‪ ,‬או‬
‫‪ B .2.2‬קרא ‪ num[A] != 0‬וגם )‪.(num[A],A) <= (num[B],B‬‬
‫אירוע ‪ 2.2‬נוגד את )*(‪ .‬אם כך האירועים הבאים התרחשו לפי הסדר הבא‪:‬‬
‫)‪num_B is set -> read_B(flag[A] = false‬‬
‫)‪-> read_B(num[A] = 0‬‬
‫‪-> num_A is set‬‬
‫סתירה ל )*(‪.‬‬
‫סעיף ב‪:‬‬
‫טענה‪ :‬האלגוריתם המוצע הינו ‪.deadlock-free‬‬
‫הוכחה‪ :‬נניח בשלילה כי האלגוריתם איננו ‪ deadlock-free‬כלומר קיימת קבוצה לא ריקה ‪X‬‬
‫אשר כל חבריה תקועים ב ‪ Entry Code‬שלהם לנצח‪.‬‬
‫‪ .1‬נראה תחילה כי עבור כל ‪ k‬לא יתכן שאף חבר ב ‪ X‬תקוע לנצח ב )‪ .while(flag[k] == true‬נקבע‬
‫את ‪ k‬ונניח בשלילה כי תהליך ‪ x‬השייך ל ‪ x‬תקוע לנצח ב )‪ while(flag[k] == true‬לנצח‪ .‬לפי הקוד‬
‫הנחה זו מחייבת מצב שבו תהליך ‪ k‬הינו זריז יותר מ ‪ x‬בכניסה ויציאה מה ‪ CS‬ולכן בכל פעם ש‬
‫‪3‬‬
‫‪ x‬מקבל זמן ריצה הוא קורא ‪ .flag[k] = true‬אולם‪ ,‬עניין זה מחייב ש בשלב מסויים > ]‪num[k‬‬
‫]‪ num[x‬ואזי תהליך ‪ k‬ימתין ב ‪ while‬שני ובשלב זה ‪.flag[k] = false‬‬
‫‪ .2‬לפי מקרה ‪ 1‬ניתן להניח שכל התהליכים ב ‪ X‬תקועים ב ‪ while‬השני‪ .‬נשים לב כי היות וישנו‬
‫תמיד תהליך ‪ x‬העל ערך )‪ (num[x],x‬ייחודי קטן ביותר מבין כל התהליכים התקועים לכאורה‬
‫יצליח תהליך זה להיכנס ל ‪.CS‬‬
‫סעיף ג‪:‬‬
‫טענה‪ :‬האלגוריתם המוצע הינו ‪.starvation-free‬‬
‫הוכחה‪ :‬נניח בשלילה שהטענה לא נכונה וכי קיים תהליך ‪ A‬אשר תקוע ב ‪ Entry code‬שלו‬
‫לנצח‪ .‬היות והאלגוריתם הינו ‪ deadlock-free‬לא קיים תהליך נוסף אשר תקוע גם הוא ב ‪Entry‬‬
‫‪ code‬שלו גם כן‪ .‬בנוסף‪ ,‬לפי מקרה ‪ 1‬של הטענה הקודמת ‪ A‬ב ‪ while‬השני‪ .‬נותרו המקרים‬
‫הבאים לשקילה‪:‬‬
‫‪.1‬‬
‫קיימים תהליכים אשר זריזים יותר מ ‪ A‬בכניסה ויציאה מן ה ‪ .CS‬זה לא יתכן שכן בשלב‬
‫מסויים ]‪ num[A‬יהיה מינימאלי ו ‪ A‬יצליח להכנס ל ‪ CS‬לפניהם‪.‬‬
‫‪.2‬‬
‫כל התהליכים שערך ה ‪ num‬שלהם קטן או שווה לשל ‪ A‬תקועים לנצח ב ‪Remainder‬‬
‫‪) code‬התהליכים עם ערך ‪ num‬גדול יותר לא חוסמים את ‪ .(A‬נשים לב שבעת יציאתם‬
‫האחרונה כל אלו קובעים ‪ .num = 0‬ואזי התנאי שעליו ‪ A‬ממתין לא מחזיק לנצח‪.‬‬
‫‪4‬‬
:3 ‫שאלה‬
‫ כבר ממתין‬0 ‫ לאחר ש‬Doorway ‫ נכנס ל‬1 ‫ אם‬.turn_to_wait = 0 ‫ נכנס להמתנה‬0 ‫ כאשר‬.‫ נכון‬.‫א‬
.0 ‫ כבר ממתין ובכך ישחרר את‬0 ‫ לאחר ש‬turn_to_wait =1 ‫אזי יקבע‬
Winner ‫ נוסיף משתנה משותף‬.‫ב‬
Algorithm for q:
//Entry code
1. Peterson_Enter_0(q,r)
2. Winner = q
3. Peterson_Enter_1(p,Winner)
<CS>
//Exit code
1. Peterson_Leave_1(p,Winner)
2. Peterson_Leave_0(q,r)
Algorithm for p:
//Entry code
1. Peterson_Enter_0(p,Winner)
<CS>
//Exit code
1. Peterson_Leave_0(p,Winner)
Algorithm for r:
//Entry code
1. Peterson_Enter_1(q,r)
2. Winner = r
3. Peterson_Enter_1(p, Winner)
<CS>
//Exit code
1. Peterson_Leave_1(p,Winner)
2. Peterson_Leave_1(q,r)
:(‫הסבר )לא נדרש כחלק מן התשובה‬
‫ עבור שני תהליכים‬Peterson ‫ נמצא תקוע בקוד הכניסה של‬r ‫ אזי‬.CS ‫ בתוך ה‬q ‫נניח כעת כי‬
.r ‫ מנסה להיכנס אזי זה יכנס לפני‬p ‫ אם בשלב זה‬.r ‫ ״ניצח״ את‬q ‫אלו שכן‬
‫ מוגנים וכי בכל רגע נתון ל‬r ‫ ו‬q ‫ המבוצעים על ידי‬Winner ‫שימו לב כי השינויים למשתנה‬
.Peterson ‫ תמיד מבצע את‬p ‫ ישנה זהות ייחודית אשר כנגדה‬WInner
.‫ ישנה עדיפות‬p ‫נבדוק כעת תרחיש להבהרה מדוע ל‬
5
‫‪.1‬‬
‫‪.2‬‬
‫‪.3‬‬
‫‪.4‬‬
‫‪.5‬‬
‫‪.6‬‬
‫‪.7‬‬
‫‪ q‬בתוך ה ‪.CS‬‬
‫‪ p‬מתחיל לבצע )‪ .Peterson_Enter_0(p,Winner‬כעת ‪ p .Winner = q‬נכנס ל ‪.busy wait‬‬
‫‪ q‬יוצא על ידי ביצוע )‪ .Peterson_Leave_1(p,Winner‬בשלב זה בפעם הבאה ש ‪ p‬ירוץ זה‬
‫יכנס ל ‪.CS‬‬
‫נראה מה קורה כאשר אנו מנסים לגרום ל ‪ r‬להשיג את ‪.p‬‬
‫נניח אם כן כי ‪ p‬לא מקבל זמן ריצה וכי ‪ q‬מבצע )‪ Peterson_Leave_0(q,r‬ולאחר מכן ‪r‬‬
‫מבצע )‪ Peterson_Enter_1(q,r‬ומנצח וקובע ‪.Winner = r‬‬
‫‪ r‬מבצע )‪.Peterson_Enter_1(p,Winner‬‬
‫זהו הזמן להיזכר בסעיף א׳ לשאלה זו‪ :‬כעת אנו במצב בו ‪ p‬התחיל המתנה ב ‪ Peterson‬לפני‬
‫ש ‪ Winner‬התחיל את ה ‪ Doorway‬שלו‪ .‬ולכן ‪ p‬יכנס קודם ל ‪.CS‬‬
‫‪6‬‬