יתרונות וחסרונות של החלפות הקשר?
יתרונות:
חסרונות:
פגיעה בנצילות המעבד (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()? (2 דברים עיקריים)
מחליפה בין מרחבי הזיכרון של התהליכים (ע”י קריאה ל-switch_mm()).
קוראת ל-switch_to_asm שמחליפה רגיסטרים (שומרת וטוענת את ההקשר).
מה הדברים העיקריים שעושה switch_to_asm?
בפונקציה switch_to_asm לאן מצביע next->thread.rsp ?
תלוי.
במקרה הסטנדרטי יהיו על המחסנית כל הרגיסטרים ש-switch_to_asm גיבתה (ולכן נוכל לשחזרם) ואח”כ כתובת החזרה של switch_to_asm.
מה הדברים העיקריים שעושה switch_to()?
מדוע הפונקציה __switch_to() מופעלת באמצעות קפיצה (פקודת jmp) ולא באמצעות קריאה רגילה (פקודת call) ?
פקודת call דוחפת למחסנית את כתובת החזרה של השורה הבאה לביצוע, ואנחנו רוצים כתובת חזרה שונה בהתאם למקרה:
בשני המקרים, מכיוון ש-__switch_to() מוגדרת כפונקציה לכל דבר, הקוד שלה מסתיים בפקודת ret ששולפת כתובת חזרה מהמחסנית (של התהליך הבא לביצוע) וקופצת אליה.
כיצד ממומש fork()?
קריאת המערכת fork() משתמשת בפונקציה פנימית של הגרעין הקרויה do_fork() לבניית ההקשר של התהליך החדש.
גם קריאות מערכת אחרות ליצירת תהליכים (לדוגמה clone()) קוראות ל-do_fork().
מהם 7 השלבים שמבצעת do_fork()?
הפונקציה do_fork() מבצעת את השלבים הבאים:
מהם שלבי הפונקציה copy_thread()?
מהם שלבי הפונקציה copy_thread()?
מה תפקיד הפונקציה ret_from_fork?
פונקציה זו מופעלת כאשר תהליך הבן מזומן לראשונה למעבד במהלך החלפת הקשר.
עושה POP_REGS ואז sysret.
למעשה, ביצוע הקוד ב-ret_from_fork יגרום לסיום הקריאה fork() בתהליך הבן עם ערך מוחזר 0.
מה עושה הפונקציה do_exit?
איך ומתי נמחק הPCB של תהליך בן?
ה-PCB של הבן מפונה רק כאשר תהליך האב מקבל חיווי על סיום התהליך, באמצעות קריאת מערכת כדוגמת wait().
מחיקת ה-PCB מבוצעת ע”י הפונקציה release_task() שנקראת מתוך המימוש של wait().
פונקציה זו, בין השאר, מנתקת את התהליך מרשימת התהליכים הגלובאלית ומטבלת הערבול PID->PCB, ומפנה את השטח המוקצה ל-PCB ומחסנית הגרעין.