תרגול 6 החלפת הקשר Flashcards
איזה רגיסטר
מצביע על הפקודה הבאה לביצוע
דגלים
רמת הרשאה נוכחית
Rip
Rflags
Cs
איפה מסומן שהגיע פסיקת חומרה
בrflags
ביט9
If
Intterhpt flaf
בגלל זה שמכבים אותו זה כיאילו כיבינו את פסיקות התוכנה
כמה פרמטרים אפשר להעביר לפונק
כמה שרוצים
6 ראשונים ברגיסטרים
השאר על המחסנית
בעת טיפול בקריאת מערכת או פסיקה מה צריך לעשות מערכת ההפעלה
איפה עושה זה? כלומר איפה שומר
איזה מקרואים עושים זו
לשמור את הרגיסטרים שהמעבד השתמש בהם
ולהחזיר אותם לפני שהוא מסיים
מגובה על מחסנית הגרעין
Push_rega
Pop_regs
יתרונות וחסרונות של החלפת הקשר
ניצול טוב יותר של משאבי המעבד במצבים כמו המתנה לדיסק
הקטנת זמן התגובה לתהליכים אינטרקטיבים
פוגע בנציחות המעבד בגלל הoverhead של החלפת הקשר
בעיקר הtlb שהולך לפח
איך קורת החלפת הקשר יזומה
התהליך עושה פעולה כלשהי שגורמת להחלפת ההקשת בעקיפין או ישירות
Read
Write
Exit
Sched_yield
פעולה שתגרום לשגיאה כמו seg fault
מה גורם להחלפת הקשת כפויה
ואיך נקראת
הפקעה
הגרעין לוקח בכוח את ההקשר
יכול לקנות בעקבות פסיקת שעון וסיום הזמן שהוקצה לתהליך
אירוע אסינכרוני שמעיר תהליך עדיף
לדוגמה תהליך זמן אמן שקיבל מהדיסק פסיקת דיסק
האם הגרעין ניתן להפקעה
כן
החלק מלינוקס 2.6
איזה פונקציית גרעין מפעילה החלפת הקשר
ולאיזה פונק היא קרואת
schedule()
היא תקרא לcontex_switch()
האם יש עוד פונקציות חוץ
מschedule()
שהו שער כניסה להחלפת הקשר
לא
איפה הרגיסטרים של תהליך נשמרים לפני החלפת ההקשר ממנו
ואיזה עוד פרט מידע צריך לשמור
במחסנית הגרעין ובpcb תחת שדה threads
את כתובת הבסיס למחסנית הגרעין
האם כל התהליכים חולקים את אותה מחסנית גרעין?
ואיל עוקבים אחרי זה?
לכל תהליך מחסנית גרעין משלו
שומרים את הבסיס אליה במבנה בשם tss
האם יש tss אחד לכל המערכת
אחד לכל מעבד
איפה בtss נשמרת הכתובת הבסיס למחסנית הגרעין
ומה צריכה לעשות החלפת ההקשר
בקשר לזה
Tss.sp0
החלפת הקשר צריכה לשנות את הערך לכתובת בסיס המחסנית גרעין של התהליך הבא
Tss ראשי תיבות
Task state segment
איפה נשמר כתובת הבסיס לtss
Tr
Register
איפה נשמר כתובת הבסיס למחסנית הגרעין לכל תהליך
ואיפה נשמר הראש שלה
בסיס בtss.sp0
ראש ב
Pcb.threads.rsp
שלבי החלפת הקשר
ברמת הפונקציות
מי ספציפית לארכיטקטורה
context_switch()
כללית ולא תלויית ארכיטקטורה
קוראת ל
__switch_to_asm()
אסמבלי כי ניגשת לרגיסטרים
תלויית ארכיטקטורה
__switch_to()
פונקצייתc
ספציפית לאריטקטורה כי ניגש למבנה tss
fork()
do_fork()
מי קורא למי
fork
קוראת ל
do_fork
כל קריאית המערכת הן כאלה
הסבר את שלבי הפעולה של
do_fork
מקצה pcb חדש ומחסנית גרעין חדשה
קוראת לפונק copy_thread()
שממלאת את מחסנית הגרעין של תהליך הבן כדי שיראה כיאילו הוא בעצמו קרא ל
Fork
ואז ל
__switch_to-asm
מעתיקה את רוב הpcb של האב לבן
Fdt ושגרת הטיפול בסיגנלים
משתמש במגנון cow כדי לחסוך זמן
מוסיפה את הבן לרשימת התהליכים הגלובלית
ולטבלת הערבול pid->pcb
מעבירה את הבן למצב task running ומכניסה אותו לrun queue
מחזירה את הpid של הבן שיחלחל בסוף לחזור לאב
Struct pt_regs
מה שומר ולמה משומש
שומר את ערכי כל הרגיסטרים
נשמרים במבנה מסוג זה בקריאה למאקרו push_regs
שמגבה את הרגיסטר למחסנית
Struct inactive_task_frame
בטיפוס כזה
שומרים את ערכי הרגיסטרים
לאחר קריאה ל
__switch-to-asm
פונקציה task_pt_regs
מה עושה
מתי בשימוש
מקבלת מצביע לpcb
ומוצאת את המבנה
Pt_regs עם ערכי הרגיסטרים של התהליך
copy_theads()
משתמשת בו כדי למצוא את ערכי הרגיסטרים של האב והבן כדי להעתיק את ערכי האב לבן
למה copy_threads
משנה את רגיסטר
Rax=0
לתהליך הבן
כי הבן מקבל 0 בחזרה מfork
בקווים כללים מה עושה
Copy_thread
מה השלבים
מעתיקה את ערכי הרגיסטר של האב לבן
משנה את rax של הבן ל0
מצביעה בrsp לראש המחסנית הגרעין של הבן
ומעדכנת את כתובת החזרה (הפונק הבאה שתקרא בעת ret) לret_from_fork בבן בלבד
מהי פונקציה
Ret_from_fork
הפונק שהבן יקרא אליה בחזרה מהfork טוענת את הרגיסטרים שclone threads שמרה בשבילו ומחזירה את הערך 0 שגם זה clone threads שמרה בשבילו
מה קורה אם תהליך מסתיים ולא קורא בעצמו לexit
הmain שלו עטוף במציאות ב
__libc_start_main
והוא קורא לexit
האם זכרון הpcb של הבן משוחרר בעת exit
לא
רק שהאב יעשה wait
איזה פונק גרעין מפנה את הpcb של בן שעשו לוwait
Release_task()
מה שלבי הפעולה של
do_exit()
משחררת משאבים בשימוש התהליך ולא הגרעין
סוגרת קבצים פתוחים, משחררת איזורי זכרון…
שומרת את ערך הסיום שלexit
בpcb->exit_code
מעדכנת את כל הבנים שלו שיהיו יתומים ויהיו בנים של init
משנה את המצב שלו לTASk_zombie
קוראת לschedule () אשר תוציא אותו מתור הריצה
בפועל מסתיים סופית שיקרא לswitch-to-asm
למה החלפת הקשר בין חוטים יותר זולה לנו
כי המטמונים לא נמחקים ולא נצטרך לבזבז זמן במילוי מחדש שלהם
setjmp & longjmp
מה אלו שתי הפונקציות האלה
למה משומשות
בעזרתם אנחנו יכולים לבצע החלפת הקשר ברמת המשתמש
קופצים אחורה וקדימה בקוד
not for exam
OmpSs
מה המוטיבציה
לפעמים למשתמש יש ידע מקדים על המשימה שהוא רוצה להריץ והוא יכול לעשות זאת באופו יותר יעיל מאשר שהגרעין ינהל לו את החלפות ההקשר בין חוטים
גם יצירת מחסנית לכל חוט היא הרבה יותר יקרה בגרעין מאשר במצב משתמש
OmpSs
מגדירה משימה כTASK
#pragma omp task inout( arr[lo:hi] )
ואז אפשר לקרוא לפונק והמגנון ינהל את הריצה המקבילה שלהן
אסור שהן יהיו תלויות אחת בשניה
אי אפשר שהמשתמש יקרא לקריאות מערכת משום שהגרעין לא מודע לכך שהמשתמש עושה את הקומבינה הזאת וכל התהליך יצא להמתנה ובעצם כל המעבד יחכה
not for exam
האם לתהליכם יש זכרון משותף k
יש אפשרות לניהול זכרון משותף בין תהליכים
בעזרת קריאות המערכת
Via system calls
1. shmget(key, sizem, attributes) // get
2. shmat(key, address, attributes) // attach
3. shmdt(address) // detach
4. shmctl(key, command, struct shmid_ds *buf) // control
5. shm_open // as file
6. shm_unlink // as file
לכל תהליך יהיו כתובות וירטואליות שונות כמובן אבל יצביעו לאותן מסגרות עם הקריאות האלה