מערכות הפעלה תרגול 5 – תהליכים ב-linux (3). מערכות הפעלה -...
Post on 19-Dec-2015
245 Views
Preview:
TRANSCRIPT
מערכות הפעלה
Linux (3)- – תהליכים ב5תרגול
מערכות הפעלה - תרגול 5 2(c) 2003 ארז חדד
תוכן התרגול
) החלפת הקשרcontext switch-ב (Linux-יצירת תהליך חדש בLinux-סיום ביצוע תהליך בLinux
מערכות הפעלה - תרגול 5 3(c) 2003 ארז חדד
Linux (1)החלפת הקשר ב-
"מעבד מריץ מספר תהליכים "בו-זמנית המעבד מריץ תהליך אחד לפרק זמן כלשהו ואז משעה את
ביצועו ועובר להמשיך להריץ תהליך אחר – "מיתוג" בין התהליכים המתבצעים
) "לכל תהליך יש "הקשר ביצועexecution context (המכיל את כל המידע הדרוש לביצוע התהליך
מחסניות, רגיסטרים, דגלים, תכולת זיכרון, קבצים פתוחים פעולת המיתוג שומרת את הקשר התהליך הנוכחי
וטוענת למעבד את הקשר הביצוע של התהליך הבא הקשר התהליך הנוכחי מתחלף – מכאן שם הפעולה
"החלפת הקשר"
מערכות הפעלה - תרגול 5 4(c) 2003 ארז חדד
Linux (2)החלפת הקשר ב- הפונקציה היחידה המפעילה את החלפת ההקשר היא
. קוד הרוצה לגרום להחלפת הקשר ()scheduleהפונקציה קורא לפונקציה זו בלבד
הפונקציהschedule() בוחרת מי יהיה התהליך הבא לזימון למעבד, כפי שראינו בתרגול הקודם, ואז קוראת לפונקציה
המבצעת את החלפת ההקשר()context_switchבשם ,כזכור מתרגול קודםschedule() והחלפת ההקשר מתבצעים
על-מנת למנוע הפעלה רקורסיבית של בפסיקות חסומותהזמן והחלפת ההקשר, דבר העלול לגרום לשיבוש פעולת
מערכת ההפעלה:החלפת הקשר היא בקירוב רצף הביצוע הבא
שמירת נתוני הקשר התהליך הנוכחי 1.
מעבר למחסנית הגרעין של התהליך הבא (שהופך להיות התהליך 2.הנוכחי החדש)
טעינת נתוני הקשר התהליך הנוכחי החדש 3.
קפיצה לכתובת הבאה לביצוע של התהליך הנוכחי החדש4.
מערכות הפעלה - תרגול 5 5(c) 2003 ארז חדד
Linux (3)החלפת הקשר ב--מרבית ההקשר של תהליך בLinux מאוחסן במתאר התהליך
ולכן אין צורך "לשמור" ו"לטעון" אותו מחדש בכל החלפת הקשר
נשמרים ונטענים בעיקר הרגיסטרים והדגלים השמירה והטעינה – במחסנית הגרעין של התהליך ובמתאר התהליך
threadבשדה פעולת החלפת ההקשר כוללת גם החלפת איזורי הזיכרון
: מאילו של התהליך User Modeאליהם המעבד ניגש ב-הנוכחי לאילו של התהליך הבא
,עם זאת, פעולת החלפת ההקשר מתבצעת באיזור הזיכרון של הגרעיןשאינו מתחלף
במהלך החלפת הקשר לא משנים את ערכי הרגיסטרים של הסגמנטים)cs, ds, ss, es למרות שאיזור הזיכרון של התהליך אכן מוחלף. הסבר ,(
בתרגול על הזיכרון הוירטואלי
מערכות הפעלה - תרגול 5 6(c) 2003 ארז חדד
Task State Segment (1)
-לכל מעבד בLinux יש איזור זיכרון בגרעין המכיל מידע מתוך הקשר התהליך הנוכחי המתבצע באותו מעבד
איזור זה קרויTask State Segment – TSS) קיומו של איזור זה הוא אילוץ של החומרהIA32(
המעבד קורא את כתובת מחסנית הגרעין של התהליך הנוכחיKernel Mode בעת מעבר ל-TSSמשדה ב-
-הTSS משמש בחומרה לפעולות נוספות כגון בקרת גישה I/Oבפעולות
-הTSS של כל המעבדים מוכלים במערך init_tss-בעת ביצוע החלפת הקשר, מעדכנים שדות בTSS
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 7(c) 2003 ארז חדד
Task State Segment (2)
ההגדרות נמצאות בקובץ הגרעיןinclude/asm/processor.h
struct tss_struct {..unsigned long esp0;..};struct tss_struct init_tss[NR_CPUS];
מצביע לבסיס מחסנית הגרעין של התהליך הנוכחי במעבד)kernel mode בכניסה ל-esp(ערך
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 8(c) 2003 ארז חדד
במתאר התהליךthreadשדה שדה זה משמש לשמירת חלק מהקשר התהליך שדה זה הוא מסוגthread_struct המוגדר בקובץ הגרעין
include/asm/processor.h:struct thread_struct {
unsigned long esp0;unsigned long eip;unsigned long esp;unsigned long fs;unsigned long gs;..union i387_union i387;..
};
מצביע לכתובת הבסיס של מחסנית הגרעין של התהליך
מאחסן את המצביע לכתובת הבאה לביצוע לאחר החלפת הקשר
מאחסן את המצביע לראש המחסנית (בגרעין) בהחלפת הקשר
gs ו-fsמאחסן את רגיסטרי הסגמנטים
מאחסן את הרגיסטרים של היחידה המתימטית
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 9(c) 2003 ארז חדד
()context_switchהפונקציה
הפונקציה המבצעת את החלפת ההקשר נקראתcontext_switch()
קובץ גרעיןkernel/sched.c פונקציה זו מבצעת את החלפת איזורי הזיכרון ואז קוראת למאקרו
switch_toהמבצע את פעולות הטעינה והשמירה הפונקציהcontext_switch() .היא חלק מאלגוריתם הזימון החדש
switch_to קיים רק X.2.4בגרסה הסטנדרטית של הגרעין
inline task_t *context_switch(task_t *prev, task_t *next) {.. קוד החלפת איזורי הזיכרוןswitch_to(prev, next, prev);return prev;
}
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 10(c) 2003 ארז חדד
switch_to (1)המאקרו
המאקרו מוגדר בקובץ הגרעיןinclude/asm/system.h :הקריאה למאקרוswitch_to(prev, next, last)
prevמצביע למתאר התהליך הנוכחי, שמוותר על המעבד nextמצביע למתאר התהליך הבא, שמקבל את המעבד last .הוא פרמטר שכבר אינו בשימוש באלגוריתם הזימון החדש
הסטנדרטית, פרמטר זה מצביע לאחר החזרה X.2.4בגרסת אל התהליך switch_to על מתאר התהליך ממנו בוצע switch_toמ-
הנוכחי
movl prev, %eaxmovl next, %edxpushl %esipushl %edipushl %ebp
) מניח שרגיסטרים אלוgccהקומפיילר ( ולכן ישswitch_toאינם משתנים עד סוף
לשמור אותם ולשחזר אותם בהמשך הרצת התהליך
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 11(c) 2003 ארז חדד
switch_to (2)המאקרו
movl %esp, prev->thread.espmovl next->thread.esp, %espmovl $1f, prev->thread.eippushl next->thread.eipjmp __switch_to 1:popl %ebppopl %edipopl %esi
החלפת מחסניות הגרעין מזו – זוnext לזו של prevשל
למעשה נקודת החלפת ימשיך מהכתובת של prevהתהליך ההקשר" כשיחזור לרוץ1התוית "
ימשיך לרוץ מכתובת זו nextהתהליך switch_to__בסיום
שחזור הרגיסטרים ממחסנית הגרעיןswitch_to לפני סיום nextשל
switch_to__ לפונקציה קפיצה
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 12(c) 2003 ארז חדד
switch_to() (1)__הפונקציה
פונקציה זו משלימה את רצף הפעולות במסגרת החלפתההקשר
קובץ גרעיןarch/i386/kernel/process.c:הפונקציה מוגדרת באופן מיוחד
void FASTCALL(__switch_to(struct task_struct *prev_p, struct task_struct *next_p));
ההגדרהFASTCALL פירושה שהפונקציה מקבלת פרמטרים ברגיסטרים ולא במחסנית
-הגדרה ייחודית לGCC:#define FASTCALL __attribute__(regparm(3))
פרמטרים מועברים ברגיסטרים 3עד eax, edx, ecx(משמאל לימין) ,לכןprev_p מועבר בתוך eax-ו next_p בתוך edx
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 13(c) 2003 ארז חדד
switch_to() (2)__הפונקציה
פונקציה זו מופעלת באמצעות קפיצה מתוך המאקרוswitch_to למעשה, מתוך הפונקציה) context_switch() (
כאשר הפרמטרים כבר ברגיסטריםjmp __switch_to
-מכיוון ש__switch_to() מוגדרת כפונקציה, הקוד שלה ששולפת כתובת חזרה מהמחסנית retמסתיים בפקודת
וקופצת אליההמחסנית היא מחסנית הגרעין של התהליך הנוכחי החדש כתובת החזרה היאnext->thread.eip כפי שהוכנסה בקוד של המאקרו
switch_to' של המשך ביצוע 1. ברוב המקרים, זוהי כתובת התוית '()context_switch בתוך הפונקציה switch_toהמאקרו
אםnext הוא תהליך שרץ פעם ראשונה, הכתובת היא אחרת כפי שנראה בהמשך
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 14(c) 2003 ארז חדד
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;..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שמירה ושחזור של
שמירה ושחזור של הרגיסטריםשל היחידה המתימטית
עדכון מצביע מחסנית הגרעיןTSSשל התהליך הנוכחי ב-
Linuxהחלפת הקשר ב-
(c) 2003 15מערכות הפעלה - תרגול 5ארז חדד
context_switch:
……
switch_to:
movl $1f, prev->thread.eip
$1f
prev
pushl next->thread.eip
nexttask_struct
esp
מחסנית הגרעין של התהליך next
1:
switch_to:__
ret
eip
nextהמשך הביצוע של
………
task_struct
$1f
thread.eip
thread.eip
thread.esp
thread.esp
מחסנית הגרעין
של התהליך
prev
$1febpediesi
מסגרת שלcontext_switch()
$1febpediesi
מסגרת שלcontext_switch()
ebpediesi
מסגרת שלcontext_switch()
מערכות הפעלה - תרגול 5 16(c) 2003 ארז חדד
)1שמירת ערכי הרגיסטרים (
-מרבית הרגיסטרים שבהם התהליך משתמש בUser Mode-נשמרים במעבר ל Kernel Mode ראינו דוגמה)
)2חלקית בתרגול המצביע למחסנית הרגילהss:esp נשמר ע"י החומרה
kernel modeבמחסנית הגרעין מייד עם תחילת המעבר ל-eflags נשמר באופן אוטומטי במחסנית הגרעין ואחריו
) בעת הקפיצה לטיפול בפסיקהcs:eipכתובת החזרה (es, ds, eax, ebp, edi, esi, edx, ecx, ebx נשמרים
בתחילת שגרת הטיפול SAVE_ALLבמחסנית הגרעין דרך בפסיקה
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 17(c) 2003 ארז חדד
)2שמירת ערכי הרגיסטרים (
?ומה לגבי שמירת הקשר הביצוע בתוך הגרעין המאקרוswitch_to אינו משפיע מבחינת ערכי רגיסטרים על
context_switch()משום שהוא מופעל ממש לפני החזרה מהפונקציה , בין הפונקציהschedule() לפונקציה context_switch() מתקיימים יחסי
caller-callee פונקציה קוראת / פונקציה נקראת, כפי שראינו בתרגול) לא מניחים שערכי הרגיסטרים פרט ()schedule), לכן בפונקציה 2
משתמריםebx, ebp, esi, ediל-ebp, esi, edi נשמרים במחסנית במאקרו switch_to
-בschedule()-וב context_switch() ערך ,ebx-מלפני הקריאה ל switch_to אינו בשימוש לאחר הקריאה
esp-ו eip נשמרים בתוך מתאר התהליך לפני ביצוע החלפת ההקשר switch_toבמאקרו
הרגיסטרים של הסגמנטים אינם משתנים בהחלפת הקשר ולכן אינםנשמרים
למעטfs-ו gs שלפעמים נמצאים בשימוש מיוחד ע"י תהליכים ולכן ,נשמרים
Linuxהחלפת הקשר ב-
מערכות הפעלה - תרגול 5 18(c) 2003 ארז חדד
Linux (1)יצירת תהליך חדש ב-
קריאות המערכת המשמשות ליצירת תהליכים) משתמשות בפונקציה פנימית ()forkחדשים (כדוגמת
לבניית ההקשר של ()do_forkשל הגרעין הקרויה התהליך החדש
קובץ גרעיןkernel/fork.c הפונקציהdo_fork() מעתיקה את מרבית הנתונים
ממתאר תהליך האב למתאר חדש של תהליך הבן שהיא יוצרת
) קבצים פתוחיםfile descriptors בעלות משותפת על ,(משאבי מערכת
העתקת תכולת הזיכרון מתבצעת בשיטה מיוחדת – פרטיםבתרגולים הבאים
מערכות הפעלה - תרגול 5 19(c) 2003 ארז חדד
Linux (2)יצירת תהליך חדש ב-
הפונקציהdo_fork() בונה מחסנית גרעין לתהליך הבן ()copy_threadע"י קריאה לפונקציה
מתאר תהליך הבן מקושר לרשימת התהליכים ו"בניSET_LINKSמשפחתו" ע"י המאקרו
-הקישור בין הpid של תהליך הבן למתאר תהליך הבן ()hash_pidמופעל ע"י קריאה ל-
תהליך הבן מועבר למצבTASK_RUNNING ומוכנס ()wake_up_process ע"י קריאה ל-runqueueל-
לסיום, הפונקציהdo_fork()-מחזירה את ה pid של תהליך הבן, וערך זה מוחזר לבסוף לתהליך האב
מערכות הפעלה - תרגול 5 20(c) 2003 ארז חדד
copy_thread() (1)הפונקציה
פונקציה זו (קובץ גרעיןarch/i386/kernel/process.c מאתחלת את תכולת ( במתאר תהליך הבן. להלן threadמחסנית הגרעין של תהליך הבן ואת שדה
תיאור של עיקר הקודpמצביע למתאר תהליך הבן regs מצביע לרגיסטרים שאוחסנו במחסנית הגרעין של האב באמצעות
kernel mode במהלך המעבר ל-SAVE_ALLהקפיצה לפסיקה ו- struct pt_regs הוא רשומה המכילה את ערכי הרגיסטרים בדיוק בסדר בו הם
SAVE_ALLמאוחסנים במחסנית באמצעות הקפיצה לפסיקה ו- struct pt_regs childregs;
child_regsמצביע על תחילת המקום בו מאוחסנים הרגיסטרים במחסנית childregs = ((struct pt_regs *)(8192 + (unsigned long) p)) – 1;
העתקת הרגיסטרים ממחסנית הגרעין של האב למחסנית הגרעין של הבןstruct_cpy(childregs, regs);
()fork מביצוע 0, לתהליך הבן מוחזר ערך 2כזכור מתרגול childregs->eax = 0;
Linuxיצירת תהליך חדש ב-
מערכות הפעלה - תרגול 5 21(c) 2003 ארז חדד
copy_thread() (2)הפונקציה
p->thread.espצריך להצביע על ראש מחסנית הגרעין בתחילת הביצוע p->thread.esp = (unsigned long) childregs;
p->thread.esp0צריך להצביע על בסיס מחסנית הגרעין p->thread.esp0 = (unsigned long) (childregs + 1);
ret_from_forkבתחילת הביצוע תהליך הבן יריץ את p->thread.eip = (unsigned long) ret_from_fork;/* save fs and gs registers in thread field *//* copy saved math regs in thread field from father to son */
מערכות הפעלה - תרגול 5 22(c) 2003 ארז חדד
()ret_from_forkהפונקציה
פונקציה זו מופעלת כאשר תהליך הבן מזומן לראשונה למעבדלאחר החלפת הקשר
הפונקציה מוגדרת בקובץ הגרעיןarch/i386/kernel/entry.Sret_from_fork:
..jmp ret_from_syscall
ביצוע 2כפי שראינו בתרגול ,ret_from_syscall ייגרום לתהליך לאחר שנשלפו כל הרגיסטרים user modeהבן לחזור ל-
מהמחסנית-למעשה, ביצוע הקוד בret_from_fork ייגרום לסיום הקריאה
fork() 0 בתהליך הבן עם ערך מוחזר
מערכות הפעלה - תרגול 5 23(c) 2003 ארז חדד
ss
esp
eflags
cs
eip
orig_eax
es
ds
eax=0
ebp
edi
esi
edx
ecx
ebx
SAVE_ALLנשמר על ידי
נשמר בכל תחילת eaxערך טיפול בפסיקה
נשמר על ידי הקפיצה לפסיקה
מצביע למחסנית user modeהתהליך ב-
.
.
.
ret_from_fork
.
.
.
struct pt_regs
task_struct
thread.esp0
thread.eip
thread.esp
p
מערכות הפעלה - תרגול 5 24(c) 2003 ארז חדד
)1סיום ביצוע תהליך (
תהליך מסיים את ביצוע הקוד ע"י קריאת המערכתexit()
-אם קוד התהליך לא קורא במפורש לexit() מתבצעת , ()main לאחר שהפונקציה ()exitקריאה אוטומטית ל-
libcחוזרת, מתוך הספריה מתוך פונקצית הספריה__libc_start_main() שקוראת
בתחילת ביצוע התכנית()mainל- ביצוע קוד תהליך יכול גם להיקטע בעקבות אירועים
נוספים תקלה לא מטופלת במהלך ביצוע הקוד, כגון גישה לא חוקית
0לזיכרון או חלוקה ב-הריגת תהליך אחד על-ידי תהליך אחר
מערכות הפעלה - תרגול 5 25(c) 2003 ארז חדד
)2סיום ביצוע תהליך ( הפונקציהdo_exit() מופעלת בכל מקרה של סיום
ביצוע התהליך קובץ גרעיןkernel/exit.c
:בין השאר, פונקציה זו מבצעת את הפעולות הבאותמשחררת את המשאבים שבשימוש התהליך מעדכנת שדהexit_code במתאר התהליך להכיל את
()exitהערך המוחזר ע"י מעדכנת קשרי משפחה: כל בניו של התהליך שסיים
initהופכים להיות בנים של -מעבירה את מצב התהליך לTASK_ZOMBIE-קוראת לschedule() שמוציאה את התהליך ,
ומזמנת תהליך אחר לביצוע במעבד. ביצוע runqueueמה-switch_toהתהליך מסתיים סופית בביצוע
מערכות הפעלה - תרגול 5 26(c) 2003 ארז חדד
)3סיום ביצוע תהליך (
מתאר התהליך מפונה רק כאשר תהליך האב מקבלחיווי על סיום התהליך, באמצעות קריאה כדוגמת
wait() פינוי מתאר התהליך מבוצע ע"י הפונקציה
release_task() קובץ גרעיןkernel/exit.c
פונקציה זו, בין השאר, מנתקת את התהליך מרשימת pid) וממנגנון הקישור ל-REMOVE_LINKSהתהליכים (
(unhash_pid()) ומפנה את השטח המוקצה למתאר ,התהליך ומחסנית הגרעין
top related