מערכות הפעלה

Download Report

Transcript מערכות הפעלה

‫מערכות הפעלה‬
‫תרגול ‪ – 5‬מימוש זמן תהליכים‬
‫מה בתכנית?‬
‫‪ ‬כמה מילים על ניהול זיכרון ב‪XINU-‬‬
‫‪ ‬ארכיטקטורת ‪ - x86‬תזכורת‬
‫‪ ‬מימוש זמן תהליכים ב‪XINU-‬‬
‫‪ ‬איך לשנות ‪XINU‬‬
‫‪2‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫ניהול זיכרון‬
‫הקצאה ושחרור זכרון נעשים באמצעות ‪ getmem/freemem‬בהתאמה‬
‫(בדומה ל‪ malloc/free-‬בשפת )‪.‬‬
‫;) >גודל בבתים< (‪> = getmem‬מצביע לבלוק<‬
‫‪ getmem‬מחזירה מצביע למקום הזיכרון שהוקצה‪ .‬אם אין מקום מתאים‬
‫יוחזר ‪.NULL‬‬
‫‪3‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫ניהול זיכרון‬
‫;) >גודל הבלוק< ‪>,‬מצביע לבלוק<(‪freemem‬‬
‫‪ freemem‬משחררת את מספר הבתים שצויין מהמקום בזכרון שסופק‬
‫כפרמטר‪.‬‬
‫המצביע חייב להיות זה שהתקבל בקריאה קודמת כלשהי ל‪.getmem-‬‬
‫‪‬‬
‫‪‬‬
‫‪4‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫מרחב הכתובות בזכרון‬
‫‪ ‬המעבד מסוגל לגשת למרחב הכתבות של ‪1MB‬‬
‫‪ ‬כל כתובת ניתנת לייצוג על ידי ‪ 20‬ביטים‪ ,‬אבל מילת המכונה היא‬
‫בגודל ‪ 16‬ביט‬
‫‪ ‬נעזרים ב‪ 2-‬מילים‪<Segment>:<Offset> :‬‬
‫‪ ‬הנוסחה לכתובת אבסולוטית‪:‬‬
‫>‪<Address> = <Segment> * 16 + <Offset‬‬
‫‪ ‬דוגמה‪:‬‬
‫‪1300:2A03 = 1300 * 0x10 + 2A03 = 13000 + 2A03 = 15A03‬‬
‫‪5‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫מרחב הכתובות בזכרון‬
‫‪ ‬דוגמה‪:‬‬
‫‪1300:2A03 = 1300 * 0x10 + 2A03 = 13000 + 2A03 = 15A03‬‬
‫נחשב גם ‪15A0:0003‬‬
‫‪‬‬
‫‪15A0:0003 = 15A03‬‬
‫מכאן שלאותה כתובת אבסולוטית יכולים להיות מספר ייצוגים במבנה הזה‬
‫‪6‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫רגיסטרים‬
‫רגיסטרים לשימוש כללי‪ ,‬איתם ניתן לבצע‬
‫פעולות אריתמטיות ואחרות‬
‫רגיסטרי אינדקס‬
‫)‪SI (source), DI (destination‬‬
‫רגיסטרי סגמנט‪ :‬שומרים ערכי סגמנטים של‬
‫מקומות מיוחדים בזכרון‬
‫מצביע על ראש המחסנית‬
‫)‪SS (Stack‬‬
‫)‪CS (Code‬‬
‫)‪DS (Data‬‬
‫)‪ES (Extra Data‬‬
‫)‪SP (Stack pointer‬‬
‫מצביע לפקודה הבאה בקוד התכנית‬
‫)‪IP (Instruction pointer‬‬
‫מצביע על פרמטרים של הפונקציה הנקראת‬
‫דגלים‬
‫‪7‬‬
‫‪AX (accumulator),‬‬
‫‪BX (base),‬‬
‫‪CX (counter),‬‬
‫)‪DX (data‬‬
‫)‪BP (Base pointer‬‬
‫‪Flags‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫הבהרות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪ DX ,CX ,BX ,AX‬הם רגיסטרים בגודל מילה אחת‪ ,‬אך ניתן להשתמש‬
‫בכל אחד מהם כשני רגיסטרים בגודל בית אחד (‪)AL ,AH‬‬
‫‪ SS‬מחזיק את סגמנט המחסנית‬
‫כדי לגשת לבסיס המחסנית נשתמש ב‪SS:0-‬‬
‫כדי לגשת לראש המחסנית נשתמש ב‪SS:SP-‬‬
‫‪ IP‬מצביע לפקודה הבאה לביצוע בסגמנט הקוד‪ .‬לכן‪ CS:IP ,‬מכיל את‬
‫הכתובת האבסולוטית של הפקודה הבאה לביצוע‬
‫‪ BP‬מצביע על הפרמטרים שנשלחו על המחסנית לפונקציה המתבצעת‬
‫("הפונקציה הנקראת")‪ .‬על ידי שימוש במרחק יחסי מה‪ BP-‬ניתן להגיע‬
‫לפרמטרים שונים‪ ,‬לכתובת החזרה מהפונקציה ולמשתנים הלוקליים‬
‫לדוגמה‪ ,‬הפרמטר הראשון נמצא ב‪ .[BP+4]-‬כדי להגיע לכתובת‬
‫אבסולוטית יש להשתמש בסגמנט השמור ב‪.SS-‬‬
‫‪8‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫רגיסטר ‪FLAGS‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫כולל את ביט אישור הפסיקות וכן ביטי ‪Condition code‬‬
‫הביטים שבשימוש על ידי ‪ XINU‬הם‪:‬‬
‫‪0‬‬
‫‪6‬‬
‫‪9‬‬
‫‪CF‬‬
‫‪ZF‬‬
‫‪IF‬‬
‫‪ : (Zero Flag) ZF‬מציין האם הערך האחרון שחושב הינו ‪0‬‬
‫‪ : )Carry Flag( CF‬מציין האם בעת חישוב הערך האחרון נוצר ‪Сarry‬‬
‫אל מעבר לביט העליון של המילה (כאשר יש גלישה)‬
‫‪: )Interrupt Flag( IF‬‬
‫‪‬‬
‫‪‬‬
‫‪9‬‬
‫כשכבוי‪ :‬פסיקות (חומרה בלבד) לא מאופשרת‬
‫כשדלוק‪ :‬פסיקות מאופשרות‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫רגיסטר ‪FLAGS‬‬
‫‪‬‬
‫‪: )Interrupt Flag( IF‬‬
‫‪ ‬כשכבוי‪ :‬פסיקות (חומרה בלבד) לא מאופשרת‬
‫‪ ‬כשדלוק‪ :‬פסיקות מאופשרות‬
‫‪ ‬פסיקות חמרה (דיסק‪ ,‬מקלדת‪ ,‬מסך‪ ,‬שעון וכו') קורות‬
‫כתוצאה משינוי מצב של חמרה (תו הוקש במקלדת‪ ,‬תזוזת‬
‫ראש הדיסק הסתיימה וכדומה)‪.‬‬
‫‪ ‬דגל ‪ IF‬מורה האם לשרת פסיקות מסוג זה‪ .‬ניתן לכבות או‬
‫להדליק את הדגל דרך פקודות המכונה‪cli, sti :‬‬
‫‪10‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫וקטור הפסיקות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫טיפול בפסיקה מתבצע באמצעות הרצת שגרה מיוחדת‬
‫האחראית לטפל באותה פסיקה‪ .‬לשגרה כזאת קוראים ‪ISR‬‬
‫– ‪Interrupt Service Routine‬‬
‫למבנה נתונים המקשר בין כל מספר פסיקה לשגרת הטיפול‬
‫בה קוראים וקטור פסיקות‬
‫כתובת שגרת ‪ 4 :ISR‬בתים (‪ 2‬סגמנט‪ 2 ,‬אופסט)‬
‫‪ 1K‬בזכרון לשמירת כל הכתובות (=‪ 1024‬בתים)‬
‫הפסיקות המזוהות ע"י מס' ‪ .0..FF‬כשמגיעה פסיקה מס' ‪, v‬‬
‫מריצים את שגרת הטיפול הנמצאת בזכרון בכתובת ‪.4v‬‬
‫‪11‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫חריגות‬
‫‪‬‬
‫חריגות (למשל חלוק באפס‪ ,‬גישה לזכרון לא קיים‪ ,‬נפילת‬
‫מתח) מטופלות כפסיקות‪.‬‬
‫‪‬‬
‫דוגמאות‪:‬‬
‫‪ ‬כניסה ‪ 0‬בוקטור הפסיקות שמורה לחריגה – חילוק באפס‬
‫‪ ‬כניסה ‪ 4‬שמורה עבור גלישה (‪)overflow‬‬
‫‪12‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫פסיקות תכנה‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫ניתן "לייצר" פסיקות באמצעות פקודת האסמבלר ‪.int‬‬
‫פסיקות אלו נקראות פסיקות תכנה‬
‫תחביר‪:‬‬
‫;>מספר פסיקה< ‪int‬‬
‫דוגמה‪ :‬פסיקת ‪breakpoint‬‬
‫;‪int 3‬‬
‫‪13‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫סוגי פסיקות ב‪XINU-‬‬
‫מספר‬
‫סוג‬
‫‪00‬‬
‫חריגה‬
‫תאור‬
‫שם‬
‫חילוק באפס‬
‫‪08‬‬
‫חומרה‬
‫‪CLK_INT‬‬
‫פסיקת שעון (כ‪ 18.2‬פעמים בשנייה)‬
‫‪09‬‬
‫חומרה‬
‫‪KBD_INT‬‬
‫לחיצה על מקלדת‬
‫‪10‬‬
‫תוכנה‬
‫‪VID‬‬
‫שרותי תצוגת מסך‬
‫‪13‬‬
‫תוכנה‬
‫‪DSK‬‬
‫שרותי דיסק‬
‫‪16‬‬
‫תוכנה‬
‫‪KBD‬‬
‫שרותי קלט מהמקלדת‬
‫‪18‬‬
‫תוכנה‬
‫‪Ctrl_Break‬‬
‫נקראת ב‪Ctrl-Break-‬‬
‫‪14‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫סביבת ריצה‬
‫‪‬‬
‫התוכנה ב‪ XINU-‬נחלקת לשני סגמנטים‪:‬‬
‫‪ ‬סגמנט קוד המוצבע ע"י ‪CS‬‬
‫‪ ‬סגמנט נתונים ומחסנית המוצבע ע"י ‪SS ,DS‬‬
‫‪‬‬
‫‪‬‬
‫סגמנט הקוד (‪ )CS‬כולל את הקוד של כל האפליקציה‪ ,‬וכל‬
‫התהליכים‬
‫סגמנט הנתונים (‪ )DS‬כולל את כל הנתונים הסטטיים‬
‫בזכרון‪ ,‬את המחסניות של כל התהליכים ואת שטח הזכרון‬
‫המיועד להקצאות זכרון דינמיות‬
‫‪15‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫סביבת ריצה‬
‫‪‬‬
‫נשים לב – ב‪ XINU-‬כל התהליכים משתפים את‪:‬‬
‫‪ ‬אותו קוד‬
‫‪ ‬אותם נתונים סטטיים (משתנים גלובליים)‬
‫‪ ‬אותו אזור להקצאה דינמית (כך ששימוש לא נכון יכול לדרוס‬
‫זכרון שהוקצה ע"י תהליכים אחרים)‬
‫‪‬‬
‫אולם‪ ,‬לכל תהליך יש מחסנית נפרדת השייכת לו בלבד‬
‫‪16‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה‬
‫קריאה לפונקציה מתבצעת בכמה שלבים‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪17‬‬
‫באחריות הפונקציה הקוראת לשמור את ערכי הרגיסטרים‬
‫‪ DX ,CX ,BX ,AX‬במידה שידרשו לאחר החזרה‬
‫הפונקציה הקוראת דוחפת את הפרמטרים על המחסנית‬
‫(בסדר הפוך)‬
‫ביצוע פקודת המכונה לקריאה לפונקציה (שומרת כתובת‬
‫החזרה על המחסנית)‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה‬
‫בהמשך‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪18‬‬
‫באחריות הפונקציה הנקראת לשמור את ערכי הרגיסטרים‬
‫‪( DI ,SI ,BP‬ואת ‪ Flags‬אם מבצעים ‪ )CLI ,STI‬ולהקצות‬
‫על המחסנית מקום למשתניה הלוקליים‬
‫ערך הפונקציה מוחזר ברגיסטר ‪AX‬‬
‫אחרי החזרה‪ ,‬הפונקציה הקוראת אחראית להוציא את‬
‫הפרמטרים מהמחסנית‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה – מצב המחסנית‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫באחריות‬
‫הפונקציה‬
‫הקוראת‬
‫פרמטר ‪3‬‬
‫פרמטר ‪2‬‬
‫פרמטר ‪1‬‬
‫כתובת חזרה‬
‫‪bp‬‬
‫באחריות‬
‫הפונקציה‬
‫הנקראת‬
‫‪BP‬‬
‫לפני ביצוע ‪call‬‬
‫לאחר ביצוע ‪call‬‬
‫(תחילת ביצוע הנקראת)‬
‫משתנים מקומיים‬
‫‪SI‬‬
‫‪DI‬‬
‫‪.‬‬
‫‪.‬‬
‫‪.‬‬
‫‪19‬‬
‫‪ sp‬לפני‬
‫הקריאה‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫‪ sp‬בזמן ביצוע‬
‫הפונקציה הנקראת‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה – הערות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪20‬‬
‫אין צורך לשמור רגיסטרים בהם הפונקציה הקוראת לא‬
‫משתמשת‬
‫סדר דחיפת הפרמטרים הוא הפוך‪ :‬הפרמטר הראשון הוא‬
‫הקרוב ביותר לכתובת החזרה (‪)BP + 4‬‬
‫כתובת חזרה נלקחת מ‪ .CS:IP-‬בעת הקריאה ‪ IP‬כבר‬
‫מצביע על הפקודה שאחרי הקריאה לפונקציה‪ ,‬ולכן זוהי‬
‫כתובת החזרה ממנה‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה – הערות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪21‬‬
‫‪ BP‬נשמר על המחסנית לפני עדכונו‪ .‬בכך מבטיחים שכל‬
‫ערכי ‪BP‬מהווים מעין רשימה מקושרת כך שכשיוצאים‬
‫מפונקציה ניתן לשחזר את הערך הקודם‬
‫משתנים לוקליים "מוקצים" מתוך המחסנית (פשוט על ידי‬
‫קידום ‪ .)SP‬בכך מבטיחים שכאשר יוצאים מהפונקציה כל‬
‫המשתנים הלוקליים משתחררים באופן אוטומטי‬
‫בדרך כלל ‪ AX‬מספיק כדי להחזיר את ערך החזרה‬
‫מהפונקציה‪ .‬אם יש צורך להחזיר מצביע מפורש‬
‫(‪ )Seg:Off‬יוחזר הערך ב‪DX:AX-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה לפונקציה – דוגמה‬
:‫ מחברת שני מספרים ומחזירה את סכומם‬my_add ‫פונקציה‬
sum = my_add(4, 6);
:‫באסמבלר‬
_my_add proc near
push bp
mov bp, sp
push si
push di
mov bx, [bp+4]
mov cx, [bp+6]
mov ax, bx
mov bx, cx
add ax, bx
pop di
pop si
pop bp
ret
_my_add endp
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
22
‫מנגנון החלפת התהליכים‬
‫‪ ‬העובדה שהמעבד משרת תהליך מסויים נובעת‬
‫בעיקר מכך שאוגרי המעבד מכילים את הערכים‬
‫"שלו"‬
‫‪ ‬ראינו שזה קובע את הפקודות הבאות לביצוע‪,‬‬
‫המחסנית הנוכחית‪ ,‬ערכי האוגרים – ההקשר‬
‫‪ ‬החלפת התהליכים היא פעולת החלפת הקשר‬
‫(‪ – )context switch‬שמירת ההקשר של תהליך‬
‫יוצא וטעינת ההקשר של תהליך נכנס‬
‫‪23‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫מנגנון החלפת התהליכים‬
‫בנוסף להחלפת ההקשר להחלפת התהליכים שתי‬
‫מחויבויות נוספות‪:‬‬
‫‪ ‬מימוש מדיניות החלפת התהליכים‬
‫‪ ‬עדכון מבנה נתונים גלובלי של ‪XINU‬‬
‫‪24‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫החלפת הקשר‬
‫‪‬‬
‫‪‬‬
‫בזמן החלפת הקשר של התהליך הנוכחי יש לשמור את‬
‫ההקשר שלו ולטעון למעבד את ההקשר של התהליך‬
‫המחליף‬
‫ההקשר כולל‪:‬‬
‫‪ ‬ערכי אוגרים‬
‫‪ ‬ערך ‪Flags‬‬
‫‪ ‬הכתובת הבאה לביצוע (‪)CP:IP‬‬
‫‪ ‬המחסנית של התהליך‬
‫‪‬‬
‫‪‬‬
‫‪25‬‬
‫ההקשר נשמר על גבי המחסנית של התהליך‬
‫מצביע המחסנית נשמר בטבלת התהליכים‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫החלפת הקשר‬
‫‪ ‬בהחלפת ההקשר יש גם לעדכן משתנים נוספים‬
‫המציינים את מצבי התהליכים‪:‬‬
‫‪ ‬משתנה ‪ – currpid‬המציין את התהליך הנוכחי‬
‫‪ ‬מצבי התהליכים בטבלת התהליכים‬
‫‪ ‬עדכון תור ‪)getlast/insert( READY‬‬
‫‪ ‬ב‪ XINU-‬הזימון והחלפת ההקשר נעשות ע"י‬
‫פונקציות ‪ resched‬ו‪( ctxsw-‬במידה ויש החלפה‬
‫בפועל)‬
‫‪26‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫החלפת הקשר ‪resched -‬‬
‫‪ ‬שגרת ‪ resched‬מרכזת את כל הפעולות הדרושות‬
‫להחלפת הקשר‬
‫‪ ‬קריאה לשגרה היא רק בדיקה האם צריך לבצע‬
‫החלפת תהליך‬
‫‪ ‬יוזמי הקריאה ל‪:resched-‬‬
‫‪ ‬תהליך עצמו‬
‫‪ ‬מערכת הפעלה‬
‫‪27‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה ל‪ resched-‬ביוזמת התהליך‬
‫‪ ‬ויתור של תהליך על המעבד‬
‫‪ ‬המתנה להודעה‪/‬סמפור‪ ,‬השעייה‪ ,‬שינה‪ ,‬סוף‬
‫התהליך‬
‫‪ ‬תהליך דואג לשנות את מצבו לפני קריאה ל‪-‬‬
‫‪resched‬‬
‫‪ ‬כך גם ‪ resched‬מזהה שמדובר על ויתור‬
‫‪ ‬במצב של ויתור התהליך תמיד יוצא מהמעבד ונשאר‬
‫במצב שבחר לעצמו‬
‫‪28‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫קריאה ל‪ resched-‬ביוזמת מ"ה‬
‫‪‬‬
‫‪‬‬
‫הקריאה מתבצעת למרות שהתהליך הנוכחי מעוניין להמשיך‬
‫לרוץ‬
‫זה קורה כי‪:‬‬
‫‪ ‬הקצאת הזמן של התהליך נגמרה‬
‫‪ ‬קיים תהליך עם עדיפות יותר גבוהה שמוכן להכנם למעבד‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪29‬‬
‫התהליך מגיע לשגרה במצב ‪PRCURR‬‬
‫כאן לא בהכרח תתבצע החלפת התהליכים (לפי מדיניות‬
‫ההחלפה)‬
‫אם בכל זאת ההחלפה מתבצעת התהליך עובר למצב של‬
‫‪ PRREADY‬ונכנס לתור ה‪READY-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
proc.h - ‫טבלת תהליכים‬
#define NPROC
30
/* process state constants */
#define
#define
#define
#define
#define
#define
#define
20 ‫אפריל‬
PRCURR
PRFREE
PRREADY
PRRECV
PRSLEEP
PRSUSP
PRWAIT
'01\'
'02\'
'03\'
'04\'
'05\'
'06\'
'07\'
// process is currently running
// process slot is free
// process is on ready queue
// process waiting for message
// process is sleeping
// process is suspended
// process is on semaphore queue
2 ‫ תרגול‬- ‫מערכות הפעלה‬
30
proc.h - ‫טבלת תהליכים‬
/* process table entry */
struct
pentry
char
int
int
int
int
char
char
word
char
int
int
{
pstate;
pprio;
psem;
pmsg;
phasmsg;
*pregs;
*pbase;
plen;
pname[PNMLEN+1];
pargs;
(*paddr)();
/* process state: PRCURR, etc.
/* process priority
/* semaphore if process waiting
/* message sent to this process
/* nonzero iff pmsg is valid
/* saved environment
/* base of run time stack
/* stack length
in bytes
/* process name
/* initial number of arguments
/* initial code address
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
};
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
31
proc.h - ‫טבלת תהליכים‬
#define NULLPROC
extern
extern
extern
extern
20 ‫אפריל‬
struct
int
int
int
0
/* id of the null process; it */
/* is always eligible to run */
pentry proctab[];
numproc;
/* currently active processes
nextproc;
/* search point for free slot
currpid;
/* currently executing process
2 ‫ תרגול‬- ‫מערכות הפעלה‬
*/
*/
*/
32
resched.c - resched ‫מימוש של‬
int
{
resched()
register struct
register struct
pentry
pentry
*optr;
*nptr;
/* pointer to old process entry */
/* pointer to new process entry */
optr = &proctab[currpid];
if ( optr->pstate == PRCURR )
{
/* no switch needed if current prio. higher than next */
/* or if rescheduling is disabled ( pcxflag == 0 )
*/
if ( sys_pcxget() == 0 || lastkey(rdytail) < optr->pprio
|| ( (lastkey(rdytail) == optr->pprio) && (preempt > 0) ) )
return;
/* force context switch */
optr->pstate = PRREADY;
insert(currpid,rdyhead,optr->pprio);
} /* if */
else if ( sys_pcxget() == 0 )
{
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
33
resched.c - resched ‫מימוש של‬
} /* if */
else if ( sys_pcxget() == 0 )
{
kprintf("pid=%d state=%d name=%s",
currpid,optr->pstate,optr->pname);
panic("Reschedule impossible in this state");
} /* else if */
/* remove highest priority process at end of ready list */
nptr = &proctab[ (currpid = getlast(rdytail)) ];
nptr->pstate = PRCURR; /* mark it currently running
*/
preempt = QUANTUM;
/* reset preemption counter */
ctxsw(&optr->pregs,&nptr->pregs);
/* The OLD process returns here when resumed. */
return;
}
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
34
‫מימוש של ‪ctxsw‬‬
‫‪‬‬
‫‪‬‬
‫ההנחה היא שכל תהליך שאינו רץ כרגע נמצא באמצע הקריאה ל‪-‬‬
‫‪ctxsw‬‬
‫פעולות של ‪ctxsw‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪35‬‬
‫החלפת ערך האוגר ‪ SP‬של התהליך היוצא בזה של התהליך הנכנס – הפעלת‬
‫מחסנית של התהליך הנכנס => מעבר לתהליך הנכנס‬
‫ערך ה‪ SP‬נשמר בטבלת התהליכים‬
‫שמירת אוגרים נוספים (‪ )DI, SI‬במחסנית‬
‫התהליך מגיע לשגרה במצב ‪PRCURR‬‬
‫כאן לא בהכרח תתבצע החלפת התהליכים (לפי מדיניות ההחלפה)‬
‫אם בכל זאת ההחלפה מתבצעת התהליך עובר למצב של‬
‫‪ PRREADY‬ונכנס לתור ה‪READY-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
ctxsw.asm – ctxsw
; void ctxsw(opp,npp)
; char *opp, *npp;
; Stack contents upon entry to ctxsw:
; SP+4 => address of new context stack save area
; SP+2 => address of old context stack save area
; SP => return address
_ctxsw proc
near
push
mov
pushf
cli
push
push
mov
mov
mov
mov
pop
pop
popf
pop
ret
'‫הקשר א‬
'‫הקשר ב‬
_ctxsw
20 ‫אפריל‬
bp
bp,sp
si
di
bx,[bp+4]
[bx],sp
bx,[bp+6]
sp,[bx]
di
si
; frame pointer
; flags save interrupt condition
; disable interrupts just to be sure
; preserve registers
; old stack save address
; new stack save address
; restore interrupt state
bp
endp
2 ‫ תרגול‬- ‫מערכות הפעלה‬
36
‫שימו לב!‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪37‬‬
‫כאשר תהליך א' קורא ל‪ ,resched-‬ההקשר של התהליכים‬
‫מתחלף לפני ש‪ resched-‬נגמרת‪ ,‬אבל ‪ resched‬ממשיכה‬
‫להתבצע ובסופה היא מחזירה את החישוב לתהליך ב'‪.‬‬
‫סוף החישוב של ‪ resched‬מתבצע בהקשר של תהליך ב'‬
‫בשלב מאור יותר‪ ,‬כשתהליך א' יחזור לביצוע‪ ,‬הוא ימשיך‬
‫את הביצוע ‪( resched‬ו‪ )ctxsw-‬בדיוק מהנקודה בה הוחלף‬
‫ההקשר מקודם‪ ,‬כך שבסה"כ הוא מבצע את כל פקודות‬
‫המכונה ב‪ resched-‬וב‪ctxsw-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫המחסנית בזמן קריאה ל‪ctxsw-‬‬
‫‪‬‬
‫תסריט‪ :‬תהליך ‪ B‬התחלף בתהליך ‪ ,... ,C‬תהליך ‪D‬‬
‫התחלף בתהליך ‪ ,A‬תהליך ‪ A‬מתחלף בתהליך ‪B‬‬
‫תהליך יוצא ‪A‬‬
‫…‬
‫)‪(resched‬‬
‫לפני קריאה‬
‫‪&C -> pregs‬‬
‫‪&B -> pregs‬‬
‫‪&B -> pregs‬‬
‫‪&A -> pregs‬‬
‫‪B -> pregs‬‬
‫‪38‬‬
‫תהליך נכנס ‪B‬‬
‫…‬
‫)‪(resched‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫כתובת חזרה‬
‫‪bp‬‬
‫‪flags‬‬
‫‪si‬‬
‫‪di‬‬
‫אפריל ‪20‬‬
‫המחסנית בזמן קריאה ל‪ctxsw-‬‬
‫‪‬‬
‫תסריט‪ :‬תהליך ‪ B‬התחלף בתהליך ‪ ,... ,C‬תהליך ‪D‬‬
‫התחלף בתהליך ‪ ,A‬תהליך ‪ A‬מתחלף בתהליך ‪B‬‬
‫תהליך יוצא ‪A‬‬
‫…‬
‫)‪(resched‬‬
‫אחרי קריאה‬
‫‪&C -> pregs‬‬
‫‪&B -> pregs‬‬
‫‪&B -> pregs‬‬
‫‪&A -> pregs‬‬
‫כתובת חזרה‬
‫‪bp‬‬
‫‪flags‬‬
‫‪si‬‬
‫‪di‬‬
‫‪39‬‬
‫תהליך נכנס ‪B‬‬
‫…‬
‫)‪(resched‬‬
‫‪A -> pregs‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪resched & ctxsw‬‬
‫‪‬‬
‫‪‬‬
‫השדה היחיד בטבלת התהליכים המשמש להחלפת תהליך הוא‬
‫‪(pregs‬השומר את ערך ‪ SP‬מצביע על מחסנית)‬
‫איך נשמר כל נתון הקשר‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪40‬‬
‫אוגרים כלליים (‪ )DX,CX,BX,AX‬נשמרים על ידי הקורא ל‪ resched-‬אם‬
‫הערכים שלהם חשובים לו‬
‫‪ Flags ,BP ,DI ,SI‬נשמרים על ידי ‪ ctxsw‬על גבי המחסנית‬
‫‪ – SS ,ES ,DS ,CS‬לא משתנים ולא נשמרים (בפסיקה‪ :‬ברמת הפסיקה)‬
‫‪ IP‬נשמר ע"י פקודת ‪ call‬ל ‪ .resched-‬הערך המעודכן ברגע ההחלפה לא צריך‬
‫להישמר!‬
‫‪ SP‬ערכו לאחר הכנסת הקשר למחסנית נשמר בטבלת התהליכים ומשתחזר‬
‫אוטומטית לערכו הקודם בהוצאה מהמחסנית‬
‫משתני התהליך הנוכחי‪ ,‬שדות טבלת התהליכים ותור ‪ready‬‬
‫מעודכנים על ידי ‪resched‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫)‪eidi.asm – disable(ps‬‬
‫‪41‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪disable / restore‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪42‬‬
‫פונקציות משתמש ב‪ XINU-‬מגנות על קטעי קוד קריטים‬
‫באמצעות סמפורים ואמצעי סנכרון נוספים‬
‫גם מערכת ההפעלה צריכה להגן על קטעי קוד קריטים‬
‫שהיא מריצה‬
‫מערכת הפעלה מכילה קטעי קוד הרגישים מאוד לפסיקות‬
‫(חומרה או תוכנה)‬
‫מערכת הפעלה מבצעת מניעת פסיקות באמצעות המקרו‬
‫)‪disable(ps‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
eidi.asm - restore(ps)
ps-‫ מחזיר את הדגלים שנשמרו ב‬restore(ps)

#define restore(x) sys_restor (x)
; void sys_restor(ps)
; int ps;
_sys_restor
proc
near
pushbp
mov bp,sp
; C calling convenion
push
[bp+4]
popf
; restore flag word
pop bp
ret
_sys_restor
endp
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
43
‫)‪restore(ps‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪44‬‬
‫הדגלים השמורים במשתנה ‪ ps‬נדחפים על המחסנית ומיד‬
‫מוצאים לתוך אוגר הדגלים‬
‫‪ restore‬מחזיר את המצב הנתון ב‪ .ps-‬הוא אינו מאפשר‬
‫בכל מקרה את הפסיקות!!!‬
‫מערכת הפעלה מכילה קטעי קוד הרגישים מאוד לפסיקות‬
‫(חומרה או תוכנה)‬
‫צריך לשים לב ש‪ disable-‬מעדכן את המשתנה אותו הוא‬
‫מקבל כפרמטר‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫שימוש ב‪disable/restore-‬‬
‫‪‬‬
‫‪‬‬
‫ניתן לראת שקריאות מ"ה ב‪" XINU-‬עטופות" בצירוף‬
‫)‪ disable(ps)/restore(ps‬ו‪ ps-‬הוא המשתנה הלוקלי מסוג ‪int‬‬
‫המקרו )(‪ :enable‬מדליק את דגל הפסיקות (קורא ל‪ .)sti-‬במקרים‬
‫קיצוניים בלבד נרצה להדליק את דגל הפסיקות ללא קשר לערכו‬
‫האחרון בעת כיבויו‪ .‬על פי רוב נשתמש ב‪restore-‬‬
‫()‪;void sys_enabl‬‬
‫‪_sys_enabl‬‬
‫‪proc‬‬
‫‪near‬‬
‫‪sti‬‬
‫‪; enable interrupts‬‬
‫‪ret‬‬
‫‪_sys_enabl‬‬
‫‪endp‬‬
‫‪‬‬
‫למשתמש אסור לקרא ל‪disable/enable/restore-‬‬
‫‪45‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫)‪disable(ps)/restore(ps‬‬
‫‪ ‬מה קורה כשהתהליך מבצע קריאה מפורשת ל‪-‬‬
‫‪ resched‬בקוד ה"עטוף" ב‪?disable/restore-‬‬
‫‪ ‬האם תתאפשר החלפת תהליכים?‬
‫‪ ‬האם התהליך החדש ירוץ עם פסיקות מכובות?‬
‫‪ ‬האם זה מותר?‬
‫‪ ‬האם זה קורה בפועל?‬
‫‪46‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫)‪disable(ps)/restore(ps‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫קריאות מפורשות ל‪ resched-‬מותרות ואף נמצאות בקוד של מערכת‬
‫ההפעלה‬
‫‪ disable‬אוסר טיפול בפסיקות ולא אוסר החלפת התהליכים‪ .‬לכן‪,‬‬
‫בעת ביצוע קוד מוגן ע"י ‪ disable/restore‬לא יתבצעו החלפות‬
‫תהליכים "לא רצוניות" (ולא צפויות) אלא רק כאלו שיזומות על ידי‬
‫קריאה מפורשת ל‪resched-‬‬
‫מצב הפסיקות (דגלים) נשמר במשתנה לוקלי על מחסנית התהליך‬
‫הקורה ל‪ .resched-‬בעת החלפת תהליכים נטען‪ ,‬בין השאר‪ ,‬רגיסטר‬
‫הדגלים של התהליך החדש הנכנס לריצה‬
‫בעת שהתהליך זה יבצע ‪ restore‬הוא ישחזר את מצבו מאז הקריאה‬
‫האחרונה שלו ל‪( disable-‬מצב זה שמור על המחסנית הלוקלית‬
‫שלו)‬
‫שימו לב‪ :‬ההשפעה של ‪ disable‬לוקלית על התהליך עצמו‪,‬‬
‫וכשתהליך זה יחזור לריצה‪ ,‬ישוחזר מצבו בצורה מלאה‬
‫‪47‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫שגרות שרות – )(‪getprio(), getpid‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫מטרת שגרות שרות הינה לאפשר לאפליקציה גישה‬
‫לנתונים שנמצאים בטבלאות ומשתני מ"ה ללא גישה ישירה‬
‫טבלאות ומשתני מ"ה אינם אמורים להיות נגישים‬
‫לאפליקציה ובפרט אסורים לשינוי על ידה‬
‫‪ getprio‬מחזירה את עדיפות התהליך הרצוי‪ .‬נתון זה‬
‫נלקח מהשדא ‪ pprio‬של טבלת התהליכים‬
‫‪ getpid‬מחזירה את המזהה התהליך הנוכחי‪ .‬נתון זה‬
‫נלקח מהשדה ‪сurrpid‬‬
‫במערכות הפעלה מתקדמות משתנים וטבלאות מ"ה‬
‫נמצאים בזיכרון שאינו נגיש כלל לתהליכים רגילים‪.‬‬
‫במערכות אלה הגישה אפשרית רק דרך קריאות מ"ה‬
‫‪48‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
SYSCALL getpid)(
{
return(currpid);
}
,getpid.c – getpid()
getprio.c – getprio()
SYSCALL getprio(pid)
int
pid;
{
struct pentry
*pptr;
int
ps;
disable(ps);
if (isbad(pid) || (pptr = &proctab[pid]) -> pstate == PRFREE)
{
restore(ps);
return(SYSERR);
}
restore(ps);
return (pptr->pprio);
}
20 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
49
‫)(‪chprio.c – chprio‬‬
‫‪50‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫השעיית תהליכים‬
‫‪ ‬ניתן להשעות את פעולתו של התהליך ולמנוע ממנו‬
‫לההפך לתהליך הנוכחי‬
‫‪ ‬חידוש פעולת התהליך יעשה ע"י בקשה מפורשת‬
‫שתינתן ע"י תהליך אחר‪.‬‬
‫‪ ‬תהליך מושעה מקבל מצב ‪ .PRSUSP‬תהליך יכול‬
‫להשעות את עצמו (אבל לא לחדש את פעולת‬
‫עצמו!)‬
‫‪ suspend ‬מבצע ההשעיה בצורה שונה עבור‬
‫תהליכים במצבי ‪ PRCURR‬ו‪PRREDY-‬‬
‫‪ ‬תזכורת‪ :‬תהליך חדש נוצר במצב ‪PRSUSP‬‬
‫‪51‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪suspend.c‬‬
‫‪52‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪resume.c‬‬
‫‪53‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪resume.c‬‬
‫‪ ‬ניתן לבצע ‪ resume‬רק לתהליך מושעה‬
‫(‪)suspended‬‬
‫‪ ‬בעת הקריאה ל‪ ready-‬יכנס התהליך לתור‬
‫ה‪ready-‬‬
‫‪ ‬קורים ל‪ resched-‬בכל אופן‪ .‬אם התהליך הנכנס‬
‫בעדיפות גבוהה יותר הוא יכנס לריצה‪ .‬אחרת‬
‫התהליך הנוכחי ימשיך לרוץ‬
‫‪54‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪ready.c‬‬
‫‪55‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫)(‪kill‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫)‪ kill(pid‬מסיימת את פעולתו של תהליך ‪pid‬‬
‫בנוסף ‪ kill‬נקראת באופן אוטומטי בסיום קוד התהליך‬
‫היא משחררת את‪:‬‬
‫‪ ‬המחסנית של התהליך‬
‫‪ ‬רשומת התהליך בטבלת התהליכים‬
‫‪ ‬הוצאת רשומת התהליך מהתור בו היא נמצאת‬
‫‪ ‬עדכונים ספציפיים למצב התהליך‪ .‬למשל‪ ,‬אם תהליך מחכה‬
‫לסמפור ‪ :‬הגדלת המונה ב‪1-‬‬
‫‪ ‬במקרה של סיום התהליך הנוכחי – ביצוע ‪resched‬‬
‫‪ ‬סיום ריצת ‪ XINU‬כשמסתיימים כל התהליכים כולל תהליכי‬
‫מערכת ההפעלה‬
‫‪56‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪57‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫)(‪xdone‬‬
‫‪ ‬סיום ריצת ‪ XINU‬מתבצע ע"י השגרה ‪xdone‬‬
‫‪ ‬תפקידה לדאוג לסיום פעולת אמצעי קלט‪/‬פלט‪,‬‬
‫החזרת וקטור הפסיקות למצבו לפני הפעלת‬
‫‪ ,XINU‬להודיע הודעת סיום ולהחזיר בקרה ל‪MS-‬‬
‫‪DOS-‬‬
‫‪58‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫‪xdone.c‬‬
‫‪59‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬
‫איך לשנות ‪XINU‬‬
‫‪ ‬הוראות מפורטות נמצאות בקישור הבא‪:‬‬
‫‪http://www.cs.haifa.ac.il/courses/OS/change_xinu.txt‬‬
‫‪60‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪20‬‬