r4 context switch
TRANSCRIPT
הפעלה מערכות
הקשר–4תרגול context(החלפת switch(
התרגול תוכן
הקשר� context(החלפת switch(ב-Linuxב� חדש תהליך Linux-יצירתב� תהליך ביצוע Linuxסיום
הפעלהמערכות - 4תרגול 2)c חדד) 2003ארז
ב� תהליך ביצוע Linux-סיום
הקשר החלפת ?מהי
תהליכים� מספר מריץ "זמנית-בו"מעבדאת� משעה ואז כלשהו זמן לפרק אחד תהליך מריץ המעבד
אחר תהליך להריץ להמשיך ועובר בין"מיתוג"–ביצועוהמתבצעים התהליכים
הפעלהמערכות - 4תרגול 3)c חדד) 2003ארז
יש� תהליך ביצוע"לכל (הקשר "execution context(התהליך לביצוע הדרוש המידע כל את המכיל
זיכרון,דגלים,רגיסטרים,מחסניות� פתוחים,תכולת קבצים
וטוענת� הנוכחי התהליך הקשר את שומרת המיתוג פעולתהבא התהליך של הביצוע הקשר את למעבד
מתחלף� הנוכחי התהליך הפעולה–הקשר שם החלפת"מכאן"הקשר
ב הקשר Linux-החלפת
לתהליךLinuxב� כפויה הקשר החלפת לבצע ניתן לאב kernel-שנמצא mode.
הקשר� החלפת לבצע צורך נוצר פסיקה בעקבות היא,אםב הפעולה את יסיים שהתהליך לאחר kernelתתבצע
הפעלהמערכות - 4תרגול 4)c חדד) 2003ארז
ב הפעולה את יסיים שהתהליך לאחר -kernelתתבצעmode,ל חזרתו user-לפני mode.
שה� יש,non-preemptiveהואLinuxשל-kernelבגללנפרדים אירועים :שני
ב� הצורך context-גילוי switchשל� contextביצוע switch
הקשר בהחלפת הצורך גילוי
ב� צורך מגלים מצבים contextבארבעה switchשעון1. פסיקת על ה–בתגובה את כילה שתהליך time-לאחר sliceשלו
השגרה( ).()scheduler_tickבעקבות
מהמתנה2. תהליך של בעל–בחזרה תהליך מהמתנה משתחרר שבה פסיקהיותר טובה לריצה(עדיפות המוכנים התהליכים הרץ,משאר התהליך כולל
(
הפעלהמערכות - 4תרגול 5)c חדד) 2003ארז
)כרגע
חוסמתבטיפול3. מערכת להמתנהבקריאת לעבור הקורא לתהליך כך,הגורמתאחר תהליך להריץ מתפנה .שהמעבד
תהליך4. מרצונוכאשר המעבד על כגוןמוותר מערכת .()sched_yieldבקריאת
דגל� להדלקת גורמים הראשונים המצבים שלneed_reschedשניל,התהליך החזרה לפני נבדק userאשר mode.
הקשר4-ו3מצב� ולהחלפת זמן ל ישירה לקריאה גורמים
ב הקשר החלפת ,Linux-ביצוע
.()scheduleפונקצית�schedule()את המפעילה היחידה הפונקציה היא
ההקשר .החלפת
�schedule()למעבד לזימון הבא התהליך יהיה מי בוחרתהקודם� בתרגול שראינו כפי
הפעלהמערכות - 4תרגול 6)c חדד) 2003ארז
לפונקציה� החלפת()context_switchקוראת לביצוע.ההקשר
מתבצעות� הפונקציות חסומותשתי מנת-עלבפסיקותההקשר והחלפת הזמן של רקורסיבית הפעלה ,למנוע
ההפעלה מערכת פעולת לשיבוש לגרום העלול דברהבא� בתרגול שנראה כפי
ב הקשר החלפת ,Linux-ביצוע
הפעולות .סדר
הבא� הביצוע רצף בקירוב היא הקשר :החלפתהנוכחי1. התהליך הקשר נתוני .שמירת
הבא2. התהליך של הגרעין למחסנית שהופך(מעברהחדש הנוכחי התהליך )להיות
הפעלהמערכות - 4תרגול 7)c חדד) 2003ארז
החדש הנוכחי התהליך ).להיות
החדש3. הנוכחי התהליך הקשר נתוני .טעינת
הנוכחי4. התהליך של לביצוע הבאה לכתובת קפיצה.החדש
ב הקשר Linux-החלפתב� תהליך של ההקשר ולכןLinux-מרבית התהליך במתאר מאוחסן
צורך הקשר"לטעון"ו"לשמור"אין החלפת בכל מחדש .אותווהדגלים� הרגיסטרים בעיקר ונטענים נשמרים
והטעינה� בשדה–השמירה התהליך ובמתאר התהליך של הגרעין במחסניתthread
הפעלהמערכות - 4תרגול 8)c חדד) 2003ארז
אליהם� הזיכרון אזורי החלפת גם כוללת ההקשר החלפת פעולתב ניגש User-המעבד Mode:של לאלו הנוכחי התהליך של מאלוהבא התהליך
זאת� הגרעין,עם של הזיכרון באזור מתבצעת ההקשר החלפת שאינו,פעולתמתחלף
הסגמנטים� של הרגיסטרים ערכי את משנים לא הקשר החלפת ,cs(במהלךds, ss, es(,מוחלף אכן התהליך של הזיכרון שאזור .למרות
הוירטואלי� הזיכרון על בתרגול הסבר
Task State Segment)1(
Taskאזור� State Segment – TSSבגרעין זיכרון אזור ,הואבמעבד המתבצע הנוכחי התהליך הקשר מתוך מידע .המכיל
ב� מעבד אזורLinux-לכל .משלוTSSיש
החומרה� של אילוץ הוא זה אזור של )IA32(קיומול TSSל
הפעלהמערכות - 4תרגול 9)c חדד) 2003ארז
ב� משדה הנוכחי התהליך של הגרעין מחסנית כתובת את קורא TSS-המעבדל מעבר Kernel-בעת Mode
בפעולותTSS-ה� גישה בקרת כגון נוספות לפעולות בחומרה I/OמשמשבמערךTSS-ה� מוכלים המעבדים כל .init_tssשל
הקשר� החלפת ביצוע ב,בעת שדות .TSS-מעדכנים
Task State Segment)2(
הגרעין� בקובץ נמצאות ההגדרות
include/asm/processor.hstruct tss_struct {
הפעלהמערכות - 4תרגול 10)c חדד) 2003ארז
..
unsigned long esp0;
..
};
struct tss_struct init_tss[NR_CPUS];
התהליך של הגרעין מחסנית לבסיס מצביע
במעבד הנוכחי
לespערך( kernel-בכניסה mode(
התהליךthreadשדה במתאר
התהליך� מהקשר חלק לשמירת משמש זה שדה
מסוג� הוא זה הגרעיןthread_structשדה בקובץ המוגדרinclude/asm/processor.h:
struct thread_struct {unsigned long esp0; התהליך של הגרעין מחסנית של הבסיס לכתובת מצביע
הפעלהמערכות - 4תרגול 11)c חדד) 2003ארז
unsigned long esp0;unsigned long eip;unsigned long esp;unsigned long fs;unsigned long gs;..union i387_union i387;..
};
ך ש ן ע ס ש ס ס כ ע
הקשר החלפת לאחר לביצוע הבאה לכתובת המצביע את מאחסן
המחסנית לראש המצביע את הקשר)בגרעין(מאחסן בהחלפת
הסגמנטים רגיסטרי את gs-וfsמאחסן
המתימטית היחידה של הרגיסטרים את מאחסן
()context_switchהפונקציה
נקראת� ההקשר החלפת את המבצעת ()context_switchהפונקציהגרעין� kernel/sched.cקובץלמאקרו� קוראת ואז הזיכרון איזורי החלפת את מבצעת זו switch_toפונקציה
והשמירה הטעינה פעולות את המבצע
t t it h()ל ל
הפעלהמערכות - 4תרגול 12)c חדד) 2003ארז
החדש()context_switchהפונקציה� הזימון מאלגוריתם חלק בגרסה.היאהגרעין של רקX.2.4הסטנדרטית switch_toקיים
inline task_t *context_switch(task_t *prev, task_t *next) {
switch_mm....הזיכרון איזורי החלפת קוד
switch_to(prev, next, prev);
return prev;
}
)switch_to)1המאקרו
הגרעין� בקובץ מוגדר include/asm/system.hהמאקרולמאקרו� ,switch_to(prev:הקריאה next, last)
�prevהנוכחי התהליך למתאר המעבד,מצביע על שמוותר
�nextהבא התהליך למתאר המעבד,מצביע את שמקבל
הפעלהמערכות - 4תרגול 13)c חדד) 2003ארז
�lastהחדש הזימון באלגוריתם בשימוש אינו שכבר פרמטר בגרסת.הוא2.4.Xמ,הסטנדרטית החזרה לאחר מצביע זה עלswitch_to-פרמטר
בוצע ממנו התהליך הנוכחיswitch_toמתאר התהליך אל
movl prev, %eax
movl next, %edx
pushl %esi
pushl %edi
pushl %ebp
אלו)gcc(הקומפיילר שרגיסטרים מניח
סוף עד משתנים ישswitch_toאינם ולכן
הרצת בהמשך אותם ולשחזר אותם לשמור
התהליך
)switch_to)2המאקרו
movl %esp, prev->thread.espmovl next->thread.esp, %espmovl $1f, prev->thread.eippushl next->thread.eip
מזו הגרעין מחסניות החלפתשלprevשל זו–nextלזו
ההקשר החלפת נקודת למעשה
שלprevהתהליך מהכתובת ימשיךלרוץ"1"התוית כשיחזור
זוnextהתהליך מכתובת לרוץ ימשיך
הפעלהמערכות - 4תרגול 14)c חדד) 2003ארז
jmp __switch_to1:popl %ebppopl %edipopl %esi
ץך ךswitch_to__בסיום
הגרעין ממחסנית הרגיסטרים שחזור
סיוםnextשל switch_toלפני
switch_to__לפונקציהקפיצה
)switch_to())1__הפונקציה
ההקשר� החלפת במסגרת הפעולות רצף את משלימה זו פונקציהגרעין� arch/i386/kernel/process.cקובץ
מיוחד� באופן מוגדרת :הפונקציהvoid FASTCALL(__switch_to(struct task_struct *prev_p,
הפעלהמערכות - 4תרגול 15)c חדד) 2003ארז
struct task_struct *next_p));
פרמטריםFASTCALLההגדרה� מקבלת שהפונקציה פירושהבמחסנית ולא ברגיסטרים
ל� ייחודית ל(GCC-הגדרה סטנדרטי ):Cלא#define FASTCALL __attribute__(regparm(3))
ברגיסטרים3עד� מועברים ,eaxפרמטרים edx, ecx)לימין )משמאל
בתוךprev_p,לכן� edxבתוךnext_p-וeaxמועבר
ל� לקרוא אפשר אי רגילהswitch_to__למה ?בצורה
חדש� תהליך בהמשך,ret_from_fork–בגלל .שנראה
)switch_to())2__הפונקציה
המאקרו� מתוך קפיצה באמצעות מופעלת זו switch_toפונקציההפונקציה,למעשה( הפרמטרים)()context_switchמתוך כאשר
ברגיסטרים .כבר
jmp __switch_to
הפעלהמערכות - 4תרגול 16)c חדד) 2003ארז
ש� כפונקציה()switch_to__-מכיוון מסתיים,מוגדרת שלה הקודאליהretבפקודת וקופצת מהמחסנית חזרה כתובת .ששולפת
החדש� הנוכחי התהליך של הגרעין מחסנית היא .המחסנית
היא� החזרה המאקרוnext->thread.eipכתובת של בקוד שהוכנסה כפיswitch_to.המקרים התוית,ברוב כתובת המאקרו'1'זוהי ביצוע המשך שלswitch_toהפונקציה .()context_switchבתוך
ראשונהnextאם� פעם שרץ תהליך אחרת,הוא היא שנראההכתובת כפי.בהמשך
)switch_to())3__הפונקציהstruct thread_struct *prev = &prev_p->thread, *next = &next_p->thread;struct tss_struct *tss = init_tss + smp_processor_id();
unlazy_fpu(prev_p);
tss->esp0 = next->esp0;..
הרגיסטרים של ושחזור שמירה
המתימטית היחידה של
הגרעין מחסנית מצביע עדכון
ב הנוכחי התהליך TSS-של
הפעלהמערכות - 4תרגול 17)c חדד) 2003ארז
..movl %fs, prev->fsmovl %gs, prev->gsif (prev->fs | prev->gs | next->fs | next->gs) {
..movl next->fs, %fsmovl next->gs, %gs..
}/* load debug registers *//* load IO permission bitmap */return;
ושחזור שמירהgs-וfsשל
ך
....שאלה
contextלמה� switchקוד קטעי משלושה מורכב
?נפרדים
�context switch()-פונקציתCהנמצאת כללית
הפעלהמערכות - 4תרגול 18)c חדד) 2003ארז
�context_switch()ת הנמצאתCפונקצ ת כלל
ה של .kernel-בספריה
�switch_to–באסמבלר למעבד,מאקרו ,ספציפי
למעבד מיוחדת בספריה .i386מופיע
�__switch_to–פונקציתC,למעבד .ספציפית
context_switch:
……
switch_to:
movl $1f, prev->thread.eip
pushl next->thread.eip
switch to:
$1f
prev
task_struct
thread.eipthread.esp
הגרעין מחסנית
התהליך של
prevebpediesi
של מסגרת
context_switch()
nexttask_structמחסנית
הגרעין
של
התהליךthread.eip$1f
thread espediesi
של מסגרת
context_switch()
)c(חדד 419תרגול-הפעלהמערכות2003ארז
ret
eip
של הביצוע nextהמשך
$1febpediesi
של מסגרת
context_switch()1:
s tc _to:__……
… esp
ך
nextthread.esp
$1febpedi
של הרגיסטרים Userשמירת Mode
רגיסטר מכילשם נשמרמה נשמראיפה מתי
ss:espלמחסנית מצביע
רגילה
במחסנית"ע חומרה י
הגרעין
תחילת עם מייד
ל kernelהמעבר
ב� משתמש התהליך שבהם הרגיסטרים User-מרבית Modeל במעבר Kernel-נשמרים Mode)בתרגול חלקית דוגמה )2ראינו
הפעלהמערכות - 4תרגול 20)c חדד) 2003ארז
mode
eflagsאוטומטי באופן נשמר
הגרעין במחסנית
לטיפול קפיצה בעת
בפסיקה
cs:eipהחזרה אוטומטיכתובת באופן נשמר
אחרי הגרעין במחסנית
eflags
לטיפול קפיצה בעת
בפסיקה
es,ds,eax,
ebp,edi,esi,edx,ecx,ebx
במחסנית נשמרים
דרך SAVE_ALLהגרעיןשגרת בתחילת
בפסיקה הטיפול
של הרגיסטרים Kernelשמירת Modeהגרעין� בתוך הביצוע הקשר שמירת לגבי ?ומה
עלswitch_toהמאקרו� רגיסטרים ערכי מבחינת משפיע ,()context_switchאינומהפונקציה החזרה לפני ממש מופעל שהוא משום
�ebp, esi, edi-במאקרו ומשוחזרים במחסנית .switch_toנשמרים
�ebx– ערךebx מלפני הקריאה ל-switch_to אינו בשימוש לאחר הקריאה ולכן לא)()context_switchי "כן נשמר ומשוחזר ע(נשמר
הפעלהמערכות - 4תרגול 21)c 2003ארז חדד )
)()context_switchי "כן נשמר ומשוחזר ע(נשמר
�ecx, edx, eax - י הפונקציה "נשמרים במחסנית עschedule()
אינו משתמש בהם switch_toהמאקרו �
-callerמתקיימים יחסי ()context_switchלפונקציה ()scheduleבין הפונקציה �callee ) לכן בפונקציה , )2כפי שראינו בתרגול , פונקציה נקראת/ פונקציה קוראת
schedule() לא מניחים שערכי הרגיסטרים פרט ל-ebx, ebp, esi, edi משתמרים
�esp ו-eip נשמרים בתוךthread_struct לפני החלפת ההקשר בswitch_to.
אינם משתנים בהחלפת הקשר ולכן אינם נשמרים הרגיסטרים של הסגמנטים�
י תהליכים ולכן נשמרים"שלפעמים נמצאים בשימוש מיוחד ע, gs-ו fsלמעט �
TSSנשמר ב thread_struct.esp0השמור ב בסיס מחסנית הגרעין�
)Linux )1-יצירת תהליך חדש ב
קריאות המערכת המשמשות ליצירת תהליכים חדשים �משתמשות בפונקציה פנימית של הגרעין ) ()forkכדוגמת (
לבניית ההקשר של התהליך החדש ()do_forkהקרויה kernel/fork.cקובץ גרעין �
הפעלהמערכות - 4תרגול 22)c 2003ארז חדד )
מעתיקה את מרבית הנתונים ()do_forkהפונקציה �ממתאר תהליך האב למתאר חדש של תהליך הבן שהיא
יוצרתבעלות משותפת על משאבי , )file descriptors(קבצים פתוחים �
מערכת
פרטים –העתקת תכולת הזיכרון מתבצעת בשיטה מיוחדת �בתרגולים הבאים
)Linux )2-יצירת תהליך חדש ב
בונה מחסנית גרעין לתהליך הבן ()do_forkהפונקציה � ()copy_threadי קריאה לפונקציה "ע
בני "מתאר תהליך הבן מקושר לרשימת התהליכים ו�SET_LINKSי המאקרו "ע" משפחתו
הפעלהמערכות - 4תרגול 23)c 2003ארז חדד )
SET_LINKSי המאקרו "ע" משפחתושל תהליך הבן למתאר תהליך הבן pid-הקישור בין ה�
()hash_pid-י קריאה ל"מופעל ע-ומוכנס ל TASK_RUNNINGתהליך הבן מועבר למצב �
runqueue י קריאה ל"ע-wake_up_process()של pid-מחזירה את ה ()do_forkהפונקציה , לסיום�
וערך זה מוחזר לבסוף לתהליך האב, תהליך הבן
)copy_thread() )1הפונקציה
מאתחלת את תכולת ) arch/i386/kernel/process.cקובץ גרעין (פונקציה זו �להלן . במתאר תהליך הבן threadמחסנית הגרעין של תהליך הבן ואת שדה
תיאור של עיקר הקוד�p מצביע למתאר תהליך הבן
�regs מצביע לרגיסטרים שאוחסנו במחסנית הגרעין של האב באמצעות הקפיצהkernel mode-במהלך המעבר ל SAVE_ALL -לפסיקה ו
Linux-יצירת תהליך חדש ב
הפעלהמערכות - 4תרגול 24)c 2003ארז חדד )
kernel mode-במהלך המעבר ל SAVE_ALL -לפסיקה ו�struct pt_regs הוא רשומה המכילה את ערכי הרגיסטרים בדיוק בסדר בו הם
SAVE_ALL -מאוחסנים במחסנית באמצעות הקפיצה לפסיקה וstruct pt_regs* childregs;
childregs מצביע על תחילת המקום בו מאוחסנים הרגיסטרים במחסניתchildregs = ((struct pt_regs *)(8192 + (unsigned long) p)) – 1;
העתקת הרגיסטרים ממחסנית הגרעין של האב למחסנית הגרעין של הבןstruct_cpy(childregs, regs);
()forkמביצוע 0לתהליך הבן מוחזר ערך , 2כזכור מתרגול childregs->eax = 0;
)copy_thread() )2הפונקציה
p->thread.esp צריך להצביע על ראש מחסנית הגרעין בתחילת הביצוע
p->thread.esp = (unsigned long) childregs;
p->thread.esp0 צריך להצביע על בסיס מחסנית הגרעין
p->thread.esp0 = (unsigned long) (childregs + 1);
הפעלהמערכות - 4תרגול 25)c 2003ארז חדד )
p->thread.esp0 = (unsigned long) (childregs + 1);
ret_from_forkבתחילת הביצוע תהליך הבן יריץ את p->thread.eip = (unsigned long) ret_from_fork;
ושאותה pushl next->thread.eip ידחוף למחסנית בפקודה switch_toזו הכתובת ש
)16ראה שקף . (switch_to__יוציא מהמחסנית
/* save fs and gs registers in thread field */
/* copy saved math regs in thread field from father to son */
()ret_from_forkהפונקציה
פונקציה זו מופעלת כאשר תהליך הבן מזומן לראשונה למעבד �לאחר החלפת הקשר
arch/i386/kernel/entry.Sהפונקציה מוגדרת בקובץ הגרעין �ret_from_fork:check need_resched
הפעלהמערכות - 4תרגול 26)c 2003ארז חדד )
check need_resched…
jmp ret_from_sys_callיגרום לתהליך ret_from_sys_callביצוע , 2כפי שראינו בתרגול �
לאחר שנשלפו כל הרגיסטרים user mode- הבן לחזור למהמחסנית
()forkיגרום לסיום הקריאה ret_from_fork-ביצוע הקוד ב, למעשה�0בתהליך הבן עם ערך מוחזר
ss
esp
eflags
cs
eip
orig_eax
es
ds
נשמר בכל תחילת eaxערך
טיפול בפסיקה
נשמר על ידי הקפיצה
לפסיקה
מצביע למחסנית
user -התהליך בmode
.
.
.
ret_from_forkstruct pt_regs
task_struct
thread.esp0
thread.eip
p
הפעלהמערכות - 4תרגול 27)c 2003ארז חדד )
ds
eax=0
ebp
edi
esi
edx
ecx
ebx
SAVE_ALLנשמר על ידי
ret_from_fork
.
.
.
struct pt_regsthread.eip
thread.esp
)1(סיום ביצוע תהליך
()exitי קריאת המערכת "תהליך מסיים את ביצוע הקוד ע�מתבצעת , ()exit-אם קוד התהליך לא קורא במפורש ל�
()mainלאחר שהפונקציה ()exit-קריאה אוטומטית לlibcמתוך הספריה , חוזרת
הפעלהמערכות - 4תרגול 28)c 2003ארז חדד )
libcמתוך הספריה , חוזרת- שקוראת ל ()libc_start_main__מתוך פונקצית הספריה �
main() בתחילת ביצוע התכנית
ביצוע קוד תהליך יכול גם להיקטע בעקבות אירועים �נוספים
כגון גישה לא חוקית , תקלה לא מטופלת במהלך ביצוע הקוד�0- לזיכרון או חלוקה ב
ידי תהליך אחר- הריגת תהליך אחד על�
)2(סיום ביצוע תהליך
מופעלת בכל מקרה של סיום ביצוע ()do_exitהפונקציה �התהליך
kernel/exit.cקובץ גרעין �:פונקציה זו מבצעת את הפעולות הבאות, בין השאר�
משחררת את המשאבים שבשימוש התהליך�
הפעלהמערכות - 4תרגול 29)c 2003ארז חדד )
משחררת את המשאבים שבשימוש התהליך�
במתאר התהליך להכיל את exit_codeמעדכנת את שדה �()exitי "הערך המוחזר ע
כל בניו של התהליך שסיים הופכים : מעדכנת קשרי משפחה�initלהיות בנים של
TASK_ZOMBIE-מעבירה את מצב התהליך ל� runqueue-שמוציאה את התהליך מה, ()schedule-קוראת ל�
ביצוע התהליך מסתיים . ומזמנת תהליך אחר לביצוע במעבדswitch_toסופית בביצוע
)3(סיום ביצוע תהליך
מתאר התהליך מפונה רק כאשר תהליך האב מקבל חיווי �()waitבאמצעות קריאה כדוגמת , על סיום התהליך
י הפונקציה "פינוי מתאר התהליך מבוצע ע�release_task()
הפעלהמערכות - 4תרגול 30)c 2003ארז חדד )
release_task()kernel/exit.cקובץ גרעין �
מנתקת את התהליך מרשימת , בין השאר, פונקציה זו� pid- וממנגנון הקישור ל) REMOVE_LINKS(התהליכים
)unhash_pid()( , ומפנה את השטח המוקצה למתארהתהליך ומחסנית הגרעין