מערכות הפעלה

Download Report

Transcript מערכות הפעלה

‫מערכות הפעלה‬
‫תרגול ‪ – 5‬מימוש סנכרון תהליכים‬
‫מה בתכנית?‬
‫‪ ‬מימוש סנכרון‬
‫תהליכים ב‪XINU-‬‬
‫‪Mutexes ‬‬
‫‪2‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫אמצעי תקשורת וסינכרון‬
‫‪ ‬סמפור‬
‫‪wait(s)/signal(s) ‬‬
‫‪ ‬שליחת הודעות‬
‫‪send(pid, msg)/receive()‬‬
‫‪( mutex ‬מניעה הדדית)‬
‫‪3‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מימוש סמפורים‬
‫‪ ‬מצב התהליך – ‪PRWAIT‬‬
‫התהליך המחכה נמצא במצב ‪ PRWAIT‬המיוחד לסמפורים‬
‫‪ ‬תור לכל סמפור‬
‫לכל סמפור נשמר תור ‪ FIFO‬של התהליכים המחכים לו‪ ,‬כך‬
‫ש‪ signal-‬יוכל לשחרר את הראשון שבהם‪ ,‬ולהעבירו לתור ה‪-‬‬
‫‪ready‬‬
‫‪ ‬טבלת סמפורים ‪ semaph‬עם כניסות מסוג ‪sentry‬‬
‫‪ ‬כל כניסה מכילה מונה‪ ,‬מצביעים לתור (בטבלת ‪ )q‬ודגל הכניסה‬
‫(‪)SFREE/SUSED‬‬
‫‪ ‬ערך מזהה הסמפור ‪ sid‬הוא האינדקס של כניסתו בטבלת‬
‫הסמפורים‬
‫‪4‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מימוש סמפורים – ‪sem.h‬‬
‫‪5‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪wait.c – wait‬‬
‫‪6‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪wait‬‬
‫‪ ‬ביצוע ‪ wait‬לא מופרע באמצע ע"י מערכת‬
‫ההפעלה‪ .‬הגנה באמצעות ‪ .disable/restore‬אולם‬
‫החלפת הקשר היא אפשרית גם באמצע עקב‬
‫‪ resched‬יזום‬
‫‪ ‬לא ניתן לבצע ‪ wait‬על סמפור שלא נוצר‪ ,‬או שכבר‬
‫שוחרר‬
‫‪ ‬הכנסה לסוף תור הסמפור (כלומר ‪)FIFO‬‬
‫‪ ‬הקריאה ל‪ resched-‬הכרחית‬
‫‪7‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪– signal‬‬
‫‪signal.c‬‬
‫‪8‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪signal‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪9‬‬
‫ביצוע ‪ signal‬לא מופרע באמצע ע"י מערכת ההפעלה‪.‬‬
‫הגנה באמצעות ‪ .disable/restore‬אולם החלפת הקשר‬
‫היא אפשרית גם באמצע עקב ‪ resched‬יזום‬
‫לא ניתן לבצע ‪ signal‬על סמפור שלא נוצר‪ ,‬או שכבר‬
‫שוחרר‬
‫ההוצאה מראש תור הסמפורים (‪)FIFO‬‬
‫האם הקריאה ל‪ resched-‬הכרחית כפי שהיתה הכרחית‬
‫ב‪?wait-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫‪signaln.c‬‬
‫)(‪ ready‬מרכזת את כל‬
‫הטיפול בתור‬
‫התהליכים המוכנים‬
‫‪10‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪– screate‬‬
‫‪screate.c‬‬
‫לא ניתן ליצור‬
‫סמפור עם ערך‬
‫התחלתי שלילי‪ .‬מה‬
‫המשמעות של ערך‬
‫שלילי?‬
‫‪11‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪ – screate‬המשך‬
‫בעת אתחול‬
‫המערכת הוצב‬
‫קבוע ‪ SFREE‬לכל‬
‫רשומות הסמפורים‬
‫‪12‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪sdelete‬‬
‫‪13‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪sdelete‬‬
‫‪‬‬
‫אם‪ ,‬בעת מחיקת הסמפור‪ ,‬קיימים תהליכים המחכים לו‪ ,‬משחררים‬
‫את כל התהליכים‬
‫בסוף לולאת ‪ while‬מבצעים ‪ .resched‬האם מותר גם בתוך‬
‫הלולאה?‬
‫‪‬‬
‫לשים לב‪ :‬מחיקת סמפור כאשר יש תהליכים המחקים בתור היא‬
‫פעולה מסוכנת ולא טבעית (הרי יש סיבה שבגללה הם מחכים‬
‫לסמפור‪)...‬‬
‫ישנן מערכות הפעלה בהן לא ניתן לשחרר סמפור שתורו לא ריק‬
‫‪‬‬
‫‪‬‬
‫‪14‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫‪sreset.c‬‬
‫מה ההבדל בין קריאה‬
‫ל‪ sreset-‬לבין שתי‬
‫קריאות רצופות ל‪-‬‬
‫‪ sdelete‬ו‪?screate-‬‬
‫‪15‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫העברת הודעות ‪ -‬יישום‬
‫‪ ‬משלוח הודעות – לא חוסם‬
‫‪ ‬קבלת הודעות – חוסמת או לא חוסמת‬
‫‪ ‬בקבלה חוסמת‪ ,‬אם לא ממתינה הודעה‪ ,‬מחכים‬
‫‪ ‬השולח משאיר את ההודעה בטבלת התהליכים‪ ,‬בשדות‬
‫המיועדים לכך‬
‫‪ ‬כאשר שולח מבקש לשלוח הודעה לתהליך שעדיין לא‬
‫קרא הודעה קודמת‪ ,‬ההודעה החדשה אינה נשלחת‬
‫‪ ‬אם השולח מזהה שהתהליך המחכה נמצא במצב מחכה‬
‫להודעה‪ ,‬השולח מחזיר את התהליך המקבל לריצה‬
‫* תהליך המקבל הודעה אינו יודע מי השולח‬
‫‪16‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫הודעות ב‪XINU-‬‬
‫‪ XINU‬מוגבלת מאוד באמצעי העברת ההודעות‬
‫שלה‪.‬‬
‫סוגי העברה‪:‬‬
‫‪ ‬משלוח לא חוסם (‪ send‬למיניהם)‬
‫‪ ‬קבלה חוסמת ולא חוסמת (‪)receiveclr, receive‬‬
‫‪ ‬שליחת ההודעות לתהליך מסויים‬
‫‪17‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫הודעות ב‪XINU-‬‬
‫‪ ‬באמצעות העברת ההודעות ב‪ XINU-‬ניתן‪:‬‬
‫‪ ‬להעביר מסרים‬
‫‪ ‬לתאם בין תהליכים (בנוסף לסמפורים)‬
‫‪ ‬הגבלות‪:‬‬
‫‪ ‬הודעה באורך של שני בתים בלבד (‪)integer‬‬
‫‪ ‬כשמגיעים מספר מסרים‪ ,‬רק הראשון מתקבל והשאר‬
‫אובדים‬
‫‪18‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫העברת הודעות – מבנה נתונים‬
‫‪ ‬מצב התהליך – ‪ ,PRRECV‬תהליך מחכה נמצא‬
‫במצב ‪( PRRECV‬מיוחד להמתנה להודעות)‬
‫‪ ‬שדות ‪ pmsg‬ו‪ phasmsg-‬בטבלת התהליכים‬
‫‪ ‬ההודעה הנשלחת לתהליך מוכנסת לשדה ‪pmsg‬‬
‫ברשומת התהליך‬
‫‪ ‬השדה ‪ phasmsg‬מסמן אם יש הודעה ממתינה‬
‫‪19‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪send.c – send‬‬
‫‪20‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה – ‪send.c‬‬
‫‪ send ‬מתבצעת בצורה רצופה מבלי שתופרע ע"י‬
‫מערכת ההפעלה‬
‫‪ ‬אולם‪ ,‬החלפת ההקשר יכולה לקרות ע"י ‪resched‬‬
‫יזום‬
‫‪ ‬בדיקות תקינות כוללות בדיקה שאין כבר הודעה‬
‫המחכה עבור התהליך המקבל‬
‫‪ ‬אם התהליך מחכה מעירים אותו ומבצעים‬
‫‪resched‬‬
‫‪21‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪– receive‬‬
‫‪receive.c‬‬
‫‪22‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪–receive‬‬
‫‪receive.c‬‬
‫‪ receive ‬מתבצעת בצורה רצופה מבלי שתופרע‬
‫ע"י מערכת ההפעלה‬
‫‪ ‬אולם‪ ,‬החלפת ההקשר יכולה לקרות ע"י ‪resched‬‬
‫יזום‬
‫‪ ‬אם אין הודעה התהליך עובר למצב ‪PRRECV‬‬
‫ויוצא מהמעבד אחרי ‪resched‬‬
‫‪ ‬האם הוא נמצא בתור כלשהו? איך יחזור לפעולה?‬
‫‪ ‬למה שומרים הודעה במשתנה לוקלי ‪?msg‬‬
‫‪23‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫קריאת מערכת הפעלה ‪– receiveclr‬‬
‫‪receiveclr.c‬‬
‫‪24‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מניעה הדדית‬
‫‪ ‬המטרה היא למנוע מצב שבוא שני תהליכים יגשו‬
‫לאותו משאב בו זמנית‬
‫‪ ‬התסריט הלא רצוי הוא שתהליך אחד יתחיל לבצע‬
‫פעולה על המשאב ואז יופסק ע"י פסיקה מבלי‬
‫שיספיק לבצע את השינוי‬
‫‪ ‬במקרה כזה‪ ,‬תהליך שני יקבל את המשאב במצב‬
‫לא תקין‬
‫‪25‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫פתרון למניעה הדדית ברמת מערכת‬
‫הפעלה‬
‫‪ ‬ניתן לכבות את מנגנון הפסיקות (כיבוי ‪)IF‬‬
‫‪ ‬במערכות המודרניות משתמשים בשיטה זו‪:‬‬
‫‪ ‬בקוד הפנימי של מערכת הפעלה‬
‫‪ ‬תוכניות קלט‪/‬פלט (כגון קריאה של ‪ USB‬או רשת)‬
‫‪ ‬הפתרון חסום ברמת האפליקציה‬
‫‪26‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מניעה הדדית באמצעות ‪mutex‬‬
‫‪ ‬ראינו מימוש אפשרי של מניעה הדדית באמצעות‬
‫הסמפורים‬
‫‪ ‬בדרך כלל הדבר נעשה ע"י מימוש מנגנון נעילות‬
‫הקרוי ‪mutex‬‬
‫‪ ‬מנגנון הנעילה מזוהה עם משאב משותף שעבורו‬
‫רוצים למנוע גישה בו‪-‬זמנית‬
‫‪ ‬מנגנון הנעילות לא מבטיח שתהליך שנכנס לקטע‬
‫קריטי לא ייעצר עד שיצא ממנו‪ .‬הוא מבטיח‬
‫שתהליכים אחרים לא יכנסו לקטע קריטי נעול‬
‫‪27‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מניעה הדדית באמצעות ‪mutex‬‬
‫‪ ‬אם קטע קריטי נעול על ידי תהליך מסויים כל היתר‬
‫לא יצליחו לעבור מנעול ויעצרו בכניסה לקטע קריטי‬
‫‪ ‬המנגנון לא מסוגל לכפות את עצמו על אף תהליך‬
‫‪ ‬התהליך חייב להיות מתוכנת לגשת לקטע קריטי‬
‫דרך מנגנון הנעילות‬
‫‪28‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫הפעלת ‪mutex‬‬
‫‪ ‬שני מצבים – "פתוח" ו‪"-‬נעול"‬
‫‪ ‬התהליך שנכנס לקטע קריטי "נועל" (‪ )lock‬את‬
‫‪ ,mutex‬מבצע קטע קריטי ו"משחרר"‬
‫)‪(unlock‬את ‪ mutex‬ביציאה‬
‫‪ ‬אם תהליך מנסה לנעול מנגנון נעילות נעול‪ ,‬הוא‬
‫נעצר ומצטרף לתור הממתינים למנגנון הנעילות‬
‫‪29‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
mutex ‫קריאות‬
:‫נעילה‬
mutex_lock(&global_variable);
:‫שחרור‬
mutex_unlock(&global_variable);
:‫דוגמה‬
MUTEX_VAR mtx = MUTEX_VAR_INITIALIZER;
mutex_lock(&mtx);
critical_variable++;
mutex_unlock(&mtx);
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
30
‫מימוש מנגנון הנעילות‬
‫‪ ‬ניתן לממש את מנגנון הנעילות בעזרת סמפור‬
‫‪ ‬ניתן להשתמש בסמפור יחיד שהערך ההתחלתי‬
‫של המונה שלו הוא ‪.1‬‬
‫‪ ‬נקצה עבור כל מנגנון הנעילות רשומה המכילה‪:‬‬
‫‪ ‬סטטוס של מנגנון – סגור או פתוח‬
‫‪ ‬מספר הסמפור שהוקצה‬
‫‪ ‬שדה המציין את הבעלים הזמניים של מנגנון‬
‫‪31‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫הגדרת הרשומה – ‪mutex.h‬‬
‫‪32‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
SYSCALL mutex_lock(MUTEX_REC_PTR *mutex_var)
{
int nsem;
int ps, ans;
mutex.c
disable(ps);
if ((*mutex_var) == (MUTEX_REC_PTR)NULL)
{
nsem = screate(1);
if (nsem == SYSERR)
{
restore(ps);
return SYSERR;
};
(*mutex_var) = (MUTEX_REC_PTR) getmem(sizeof(MUTEX_REC));
(*mutex_var)->nsem = nsem;
}
ans = wait((*mutex_var)->nsem);
(*mutex_var)->pid = currpid;
restore(ps);
return ans;
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
33
‫‪mutex_lock‬‬
‫‪ ‬בנעילה ראשונה יוצרים רשומת ‪mutex‬‬
‫‪ ‬מקצים סמפור עבור המנגנון ונשמור את ה‪ sid-‬שלו‬
‫ברשומה‬
‫‪ ‬מחכים בתור לכניסה למנגנון הנעילה‬
‫‪ ‬מעדכנים את הפרטים של הבעלים הנוכחיים של‬
‫‪mutex‬‬
‫‪ ‬משחזרים פסיקות‪ .‬בפועל זה קורה פעמיים –‬
‫בתוך ‪ screate‬וגם בתוך הקריאה עצמה‬
‫‪34‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
SYSCALL mutex_unlock(MUTEX_REC_PTR *mutex_var)
{
int ps;
mutex.c
disable(ps);
if ( ((*mutex_var) == (MUTEX_REC_PTR)NULL) ||
((*mutex_var)->pid != currpid) )
return SYSERR;
if ( isempty(semaph[(*mutex_var)->nsem].sqhead))
{
sdelete((*mutex_var)->nsem);
freemem((*mutex_var), sizeof(MUTEX_REC));
(*mutex_var) = MUTEX_VAR_INITIALIZER;
restore(ps);
return OK;
} /* if */
signal((*mutex_var)->nsem);
restore(ps);
return OK;
} /* mutex_unlock */
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
35
‫‪mutex_unlock‬‬
‫‪ ‬אם התור הוא ריק הרשומה משתחררת והסמפור‬
‫נמחק‬
‫‪ ‬אם יש תהליכים המחכים בתור נקראת ‪ signal‬כדי‬
‫לשחרר את התהליך הבא‬
‫‪ ‬התהליך משחרר נעילה ויוצא מקטע קריטי‬
‫‪ ‬התהליך המשוחרר נמצא באמצע פעולת ‪ .lock‬הוא‬
‫רושם את עצמו כבעלים החדשים של ‪mutex‬‬
‫ומבצע קטע קריטי‬
‫‪36‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫דוגמה‪ :‬בנק‬
‫‪ ‬קיימים ‪ 2‬חשבונות בנק‬
‫‪ ‬הכספים עוברים מחשבון לחשבון‬
‫‪ ‬אל המשתנים הגלובליים ניגשים שני תהליכים‪:‬‬
‫‪ ‬תהליך ראשון מעביר סכומים מחשבון לחשבון‬
‫‪ ‬תהליך שני מדפיס סה"כ כסף בשני החשבונות‬
‫‪ ‬הסה"כ צריך להיות קבוע‪ .‬האם זה קורה באמת?‬
‫‪37‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
testmu1.c – 1 ‫ממוש‬
volatile int bank[2] = {450, 600};
xmain()
{
resume(create(bank1,INITSTK, INITPRIO, "proc 1", 0) );
resume(create(bank2,INITSTK, INITPRIO, "proc 2", 0) );
}
int bank1()
{
int sums[] = {100, -50, 150, -200};
int i=0, j, sum;
while(1) {
i++;
i = i % 4;
sum = sums[i];
bank[0] += sum;
for(j=0; j < 32000; j++)
;
bank[1] -= sum;
}
}
15 ‫אפריל‬
int bank2)(
{
int sum;
int i= 0;
while(1)
{
i++;
i = i % 30000;
sum = bank[0] + bank[1];
if ((sum != 1050)|| (i == 0))
printf("sum = %d\n", sum);
}
}
2 ‫ תרגול‬- ‫מערכות הפעלה‬
38
‫‪testmu1.c‬‬
‫‪ ‬הסכום הלא מתאים מודפס בכל מקרה גם פעם ב‪-‬‬
‫‪ 30000‬מקרים אם הוא מתאים‬
‫‪ ‬המימוש לא מגן על המשאב המשותף עם מנגנון‬
‫הנעילות‬
‫‪ ‬נראה גיוון מספרים בפלט‬
‫‪39‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫ פלט‬- testmu1.c
sum = 850
sum = 850
sum = 850
sum = 1200
sum = 1200
sum = 1200
sum = 1200
sum = 1150
sum = 1150
sum = 1150
sum = 1150
sum = 1000
sum = 1000
sum = 1000
sum = 850
sum = 850
sum = 850
sum = 850
15 ‫אפריל‬
‫הפלט מכיל מספרים‬
‫שונים‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
40
testmu2.c – 2 ‫ממוש‬
volatile int bank[2] = {450, 600};
xmain()
{
resume(create(bank1,INITSTK, INITPRIO, "proc 1", 0) );
resume(create(bank2,INITSTK, INITPRIO, "proc 2", 0) );
}
int bank1()
{
int sums[] = {100, -50, 150, -200};
int i=0, j, sum;
while(1) {
i++;
i = i % 4;
sum = sums[i];
mutex_lock(&mutex1);
bank[0] += sum;
bank[1] -= sum;
mutex_unlock(&mutex1);
}
}
15 ‫אפריל‬
int bank2)(
{
int sum;
int i= 0;
while(1)
{
i++;
i = i % 30000;
mutex_lock(&mutex1);
sum = bank[0] + bank[1];
mutex_unlock(&mutex1);
if ((sum != 1050)|| (i == 0))
printf("sum = %d\n", sum);
}
}
2 ‫ תרגול‬- ‫מערכות הפעלה‬
41