Context switch Flashcards
יתרונות וחסרונות של החלפות הקשר?
יתרונות:
- ניצול טוב יותר של משאבי המערכת.
- הקטנת זמן התגובה של תהליכים אינטראקטיביים.
חסרונות:
פגיעה בנצילות המעבד (CPU utilization).
מהם 2 הסוגים של החלפות הקשר?
- יזומה - התהליך מוותר מרצונו על המעבד
2. כפויה (הפקעה) - הגרעין מפקיע (כלומר, לוקח בכוח) את המעבד מהתהליך
האם גרעין לינוקס ניתן להפקעה?
בגרסאות ישנות של לינוקס, הגרעין לא היה מאפשר להפקיע את המעבד מתהליך שנמצא במצב גרעין.
אבל החל מגרסה 2.6, גרעין לינוקס מסוגל להפקיע את המעבד גם מתהליך שנמצא במצב גרעין.
האם החלפת הקשר מתבצעת במצב משתמש או במצב גרעין?
החלפת הקשר דורשת את התערבות מערכת ההפעלה, ולכן היא מתרחשת במצב גרעין.
היכן נשמרים הרגיסטרים והדגלים בעת החלפת הקשר?
השמירה והטעינה מתבצעת במחסנית הגרעין ובשדה thread ב-PCB.
איך המעבד יודע איפה נמצאת מחסנית הגרעין של התהליך הנוכחי?
באמצעות מבנה מיוחד הנקרא TSS.
במעבר בין רמות הרשאה (user mode->kernel mode) מעבדי IA-32 קוראים את השדה TSS.sp0 כדי למצוא את בסיס מחסנית הגרעין.
החלפת הקשר צריכה אם כן לעדכן את השדה TSS.sp0 כך שיצביע למחסנית הגרעין של התהליך הבא לביצוע.
Why do need a separate TSS struct for each CPU?
The TSS.sp0 serves as a “register” that points to the base of the current kernel stack. Since all registers are per-CPU, so is the TSS struct.
איך אנו ניגשים ל-TSS?
בעזרת רגיסטר ששמו TR.
מה תפקידו של השדה thread ב-PCB?
השדה thread הוא מבנה מטיפוס thread_struct אשר נמצא בתוך ה-PCB.
השדה משמש לשמירת חלק מהקשר התהליך.
פריט המידע החשוב מבחינתנו הוא המצביע לראש מחסנית הגרעין שנשמר ונטען בזמן החלפת הקשר.
מה ההבדל בין השדה thread ב-PCB לבין TSS.Sp0?
thread מכיל כאחד השדות שלו מצביע לראש מחסנית הגרעין (איפה היא מסתיימת כרגע).
TSS.SP0 לעומת זאת מצביע לבסיס מחסנית הגרעין (איפה היא מתחילה).
תאר את שלבי החלפת ההקשר.
- context_switch() – פונקצית C כללית, לא תלוית ארכיטקטורה.
- __switch_to_asm() – פונקציה ספציפית לארכיטקטורה, כתובה באסמבלי כי קוראים/כותבים לרגיסטרים.
- __switch_to() – פונקצית C, ספציפית לארכיטקטורה כי ניגשים למבנה TSS.
מה עושה הפונקציה context_switch()? (2 דברים עיקריים)
מחליפה בין מרחבי הזיכרון של התהליכים (ע”י קריאה ל-switch_mm()).
קוראת ל-switch_to_asm שמחליפה רגיסטרים (שומרת וטוענת את ההקשר).
מה הדברים העיקריים שעושה switch_to_asm?
- ראשית היא שומרת את כל הרגיסטרים לפי קונבנציות קריאה לפונקציה, כי הקומפיילר לא יודע שהולכת להתבצע החלפת הקשר ולכן על הפונקציה לגבות את הרגיסטרים שבאחריותה.
- אח”כ מחליפה מחסניות: movq %rsp, prev->thread.rsp
movq next->thread.rsp, %rsp
(prev ו next עוברים כמובן ברגיסטרים זה רק פסאודו-קוד) - שחזור הרגיסטרים ממחסנית הגרעין של next.
אלו הרגיסטרים ש-next שמר כאשר הוא קרא להחלפת הקשר בעבר. - קופצים ל-switch_to, קפיצה ולא call כי כתובת החזרה כבר שמורה על המחסנית.
בפונקציה switch_to_asm לאן מצביע next->thread.rsp ?
תלוי.
- מקרה אתחול: התהליך next הוא תהליך חדש שנוצר ע”י fork() ועדיין לא רץ אף פעם.
- מקרה סטנדרטי: התהליך next כבר רץ בעבר ועבר החלפת הקשר. במקרה זה המחסנית של next נראית כמו המחסנית של prev, כי prev הוא תהליך שעובר עכשיו החלפת הקשר!
במקרה הסטנדרטי יהיו על המחסנית כל הרגיסטרים ש-switch_to_asm גיבתה (ולכן נוכל לשחזרם) ואח”כ כתובת החזרה של switch_to_asm.
מה הדברים העיקריים שעושה switch_to()?
- update_sp0(next_p);
עדכון מצביע מחסנית הגרעין
של התהליך הנוכחי ב-TSS - return
שליפת כתובת החזרה מראש המחסנית