This question spans 3 stages — each part below is tagged with, and links to, the stage it belongs to.
הקדמה כפי שראיתם בקורס, לינוקס תומכת במדיניויות זימון שונות, כמו SCHED_RR,SCHED_OTHER ו-SCHED_FIFO. במערכת הפעלה היפותטית "FIFOix" (הדומה מאוד ל-Linux) קיימות שתי במדיניויות בלבד: • מדיניות SCHED_OTHER) other) – ברירת המחדל של המערכת. • מדיניות SCHED_FIFO) fifo) – מדיניות זימון עבור תהליכי real-time קריטיים. ניתן להדליק מדיניות זו בעזרת קריאת המערכת setfifo בלבד. קריאת המערכת setfifo תהליך FIFOix יכול לשנות את מדיניות הזימון של אחד מבניו בעל מזהה p בעזרת קריאת המערכת הבאה: int setfifo(pid_t p) הקריאה מקבלת מזהה תהליך p ובמידה וקיים, קובעת את מדיניות הזימון של התהליך להיות fifo וחוזרת עם 0. אחרת, מחזירה ערך שגיאה מתאים. שימו לב: • כל בניו העתידיים של p גם יהיו בעלי מדיניות fifo. • p חייב להיות אחד מבניו של התהליך הקורא. מבין היתר, הדבר אומר שתהליך לא יכול להפעיל את הקריאה על עצמו. עיקרו של קוד הגרעין של קריאת המערכת נתון: static int sys_setfifo(pid_t pid){ task_t *p = find_process_by_pid(pid); p->policy = SCHED_FIFO; schedule(); } שימו לב: הקוד הנתון הינו מופשט בכוונה. יש לנתחו בצורה איכותית, ללא התייחסות לשורות החסרות, ועל סמך היכרותכם עם Linux. בתרגיל זה, עליכם לתקן קוד של FIFOix Shell. ל-Shell יכולת להריץ פקודות הן במדיניות other והן במדיניות fifo. הפקודה שמקורה בשורת הפקודה (command-line) מנותחת (parse) ומתורגמת ל-struct הבא: typedef struct command { bool isfifo; // Whether to run the program in fifo mode or not char** argv; // Array of strings: First cell holds the name of the program // to run, the rest hold command line arguments int argc; // Number of filled cells in argv pid_t pid; // The pid of the executing process } command; הפונקציה ב-Shell שאחראית על ביצוע (execute) הפקודה המנותחת: pid_t execute_command(command* c) { c->pid = fork(); if (c->pid == 0) { handle_pipes(c); handle_redirections(c); execv(c->argv[], c->argv); // if we get here, execv failed printf("Error: execv failed\n"); exit(1); } assert(c->pid > 0); if (c->isfifo) setfifo(c->pid); return c->pid; } הנחות: בעת פתרון הסעיפים הבאים, הניחו שהפונקציות handle_redirections()-I handle_pipes)( כאן בשביל שלמות – אין להתייחס אליהן בעת פתרון השאלות הבאות. הקוד כאן מורץ על ידי תהליך ה-Shell. לבן הנוצר לאחר ה-fork() נקרא "cp". זכרו: ממשק קריאות המערכת השונות (כמו fork, signal וכו') מופיעות בסוף המבחן, במידה ואתם זקוקים לו. בקוד זה שני race conditions מסוכנים המתוארים בסעיפים 11 ו-12: עליכם לתקן את בעיית הסנכרון שנוצרה בעזרת קריאת המערכת הבאה: bool amfifo() קריאה זו מחזירה 1 אם לתהליך הקורא מדיניות fifo, ו-0 אם בעל עדיפות other בסעיף הבא ננצל את הפקודה האטומית הבאה: int AtomicSwap(int * x, int y) הפקודה מחליפה באופן אטומי את תכולתו של התא x בערכו של y. הפקודה מחזירה את ערכו הקודם של x. יותם הציע את התיקון הבא לבעיית הסנכרון: pid_t execute_command(command* c) { int finshed_setting = 0; // ADDED c->pid = fork(); if (c->pid == 0) { while(AtomicSwap(&finshed_setting,0)==0); // ADDED handle_pipes(c); handle_redirections(c); execv(c->argv[], c->argv); // if we get here, execv failed printf("Error: execv failed\n"); exit(1); } assert(c->pid > 0); if (c->isfifo) setfifo(c->pid); AtomicSwap(&finshed_setting, 1); // ADDED return c->pid; } אבי הציע פתרון מסוג שונה לבעיה, הנעזר במנגנון הסיגנלים: int father_finished = 0; // ADDED Global variable void update_father_status(int sig) { // ADDED father_finished = 1; // ADDED } pid_t execute_command(command* c) { signal(SIGUSR1, update_father_status); // NOTE: The signal handler is // inherited by the son c->pid = fork(); if (c->pid == 0) { while(!father_finished){}; // ADDED handle_pipes(c); handle_redirections(c); execv(c->argv[], c->argv); // if we get here, execv failed printf("Error: execv failed\n"); exit(1); } assert(c->pid > 0); if (c->isfifo) setfifo(c->pid); kill(c->pid, SIGUSR1); // ADDED return c->pid; }
Full original question text (raw OCR)
שאלה 4 – תזמון וסנברון (25 נק') – 7 סעיפים
חאסן טוען שאם נסיר את הקריאה ל-schedule(), התהליך לעולם לא ירוץ במדיניות SCHED_FIFO בפועל. האם אתם מסכימים? הסבירו.
SCHED_FIFO / SCHED_RR real-time policiesבמקרים מסוימים, cp יעבור למדיניות fifo לאחר שהתחיל לבצע את הפקודה עם execv. תארו בקצרה תרחיש בו דבר זה מתקיים.
fork/exec address-space semanticsבמקרים מסוימים, cp או אחד מבניו יכול לרוץ לעד עם מדיניות other. תארו בקצרה תרחיש בו דבר זה מתקיים.
Process state transitionsהציעו תיקון בקוד C לשתי בעיות הסנכרון בעזרת amfifo בלבד. ספקו שורת קוד יחידה המתקנת את בעיות הסנכרון וספקו את מספר השורה שלאחריה היא תופיע. הסבירו בקצרה
Process state transitionsהסבירו למה פתרונכם בסעיף 13 בזבזני מבחינת משאבי מעבד.
Process state transitionsהמימוש המוצע מקולקל (בעיית נבונות – correctness). הסבירו בקצרה מדוע.
SRT / preemptive Gantt constructionהמימוש המוצע מקולקל ( בעיית נבונות – correctness). הסבירו בקצרה מדוע.
SRT / preemptive Gantt construction
The exam question — original PDF
pages 12, 13, 14, 15Exactly as it appears on the exam paper.
Built from these components
Ordered basic → advanced. Master the earlier ones first.
Review the material
Read these before you answer — each verified slide teaches a component this question tests, and nothing from an unrelated topic is included. Tutorial slides show the actual slide image.
Process states created service provided ready preempted scheduled waiting finished or killed requires “slow” service (notably I/O) zombie running termination process is process is status collected runnable sleeping OS (234123) - processes & signals 4
SRTF (Shortest-Remaining-Time First) • Assume different jobs may arrive at different times • SJF is not optimal – As it’s not preemptive, and – A short job might arrive while a very long job is running => recall: convoy effect • SRTF is just like SJF but – Is allowed to use preemption – Hence, it’s “optimal” (assuming a zero context-switch cost etc.) • Whenever a new job arrives, or an old job terminates – SRTF schedules the job with the shortest remaining time – Thereby making an optimal decision 39 OS (234123) - scheduling
אחרי fork()parentint main() { int x = 0; pid_t p = fork(); if (p == 0) { x = 1; } else { x = 2; }}sonint main() { int x = 0; pid_t p = fork(); if (p == 0) { x = 1; } else { x = 2; }}מערכות הפעלה - תרגול 210
קריאת המערכת wait()pid_t wait(int *wstatus);פעולה: ממתינה עד אשר אחד מתהליכי הבן יסיים.פרמטרים:wstatus – מצביע למשתנה בו יאוחסנו פרטים על תהליך הבן שהסתיים.למשל, wstatus יכיל את ערך הסיום של הבן (הערך שהעביר כארגומנט ל-exit()). ערך הסיום מופיע בבית השני מתוך ארבעת בתי ה- wstatus. כדי לחלץ אותו יש לנצל את המאקרו WEXITSTATUS(*wstatus), המחזיר (*wstatus>>8) & 0xff. במידה ולא מעוניינים בסטטוס הבן שסיים, אפשר להעביר NULL.ערך מוחזר:אם אין בנים או שכל הבנים כבר סיימו ובוצע להם wait() – יוחזר מיד הערך -1.אם יש בנים שסיימו ועדיין לא בוצע עבורם wait() (כלומר הם במצב zombie – יפורט בשקופיות הבאות) – יוחזר מיד ה-pid של אחד הבנים הנ"ל.אחרת – המתנה עד שבן כלשהו יסיים.מערכות הפעלה - תרגול 214איך תהליך אב יכול לחכות לסיום כל תהליכי הבן?מבינים את החישוב?
הדפסה מתואמת למסךשימוש ב-wait() יכול לפתור את הבעיה שראינו קודם כאשר מדפיסים למסך במקביל משני תהליכים:int main() { pid_t p = fork(); if (p > 0) { // parent waits for child wait(NULL); } printf(“hello”); return 0;}מערכות הפעלה - תרגול 215
סיום תהליכיםכדי לאפשר לאב לקבל מידע על סיום הבן, לאחר שתהליך מסיים את פעולתו הוא עובר למצב מיוחד – zombie – שבו התהליך קיים כרשומת נתונים בלבד ללא שום ביצוע משימה.הרשומה נמחקת לאחר שהאב קיבל את המידע על סיום הבן באמצעות wait().שאלה: מה קורה לתהליך "יתום" (orphan), כלומר תהליך שסיים לאחר שאביו כבר סיים בלי לקרוא ל-wait() ?התהליך הופך להיות בן של init.התהליך init ממשיך להתקיים לאורך כל פעולת המערכת.אחד מתפקידיו העיקריים – המתנה לכל בניו כדי לפנות את נתוניהם לאחר סיומם.מערכות הפעלה - תרגול 219
TL;DRזַמָּן התהליכים ((scheduler הוא הרכיב במערכת ההפעלה שאחראי על בחירת התהליך הבא שירוץ על המעבד.אנחנו נלמד, בתור דוגמה, את אלגוריתם הזימון של לינוקס.אבל לפני שנלמד דוגמה "אמיתית" ומורכבת, נרצה להבין את הגישות הבסיסיות בזימון תהליכים כדי לפתח אינטואיציה.מערכות הפעלה - תרגול 52זימון תהליכים בלינוקסCFS = completely fair schedulerאלגוריתם זימון של תהליכים רגיליםSCHED_FIFO, SCHED_RRאלגוריתם זימון של תהליכי זמן אמת
דוגמת FCFSaverageResponseTime = (10 + 20 + 30) / 3 = 20כעת נסיר את הנחה 1 ("כל התהליכים רצים למשך אותו זמן"). לכל תהליך זמן ריצה משלו.תוכלו לחשוב על דוגמה שבה FCFS אינו יעיל?מערכות הפעלה - תרגול 59כל התהליכים רצים למשך אותו זמן.כל התהליכים מגיעים באותו זמן (t=0).אם תהליך התחיל לרוץ, אז הוא ירוץ עד לסיומו ללא הפסקות.התהליכים משתמשים רק במעבד ולא מבצעים I/O.זמן הריצה של כל התהליכים ידוע מראש.
אפקט השיירה (convoy effect)averageResponseTime = (100 + 110 + 120) / 3 = 110אלגוריתם FCFS עלול לסבול מ"אפקט השיירה": מצב שבו תהליך אחד ארוך מעכב הרבה תהליכים קצרים. מערכות הפעלה - תרגול 510
אלגוריתם SRTFSRTF = shortest remaining time firstנקרא גם: STCF = shortest time to completion firstאופן פעולה: כמו SJF, אבל עם הפקעות.בכל פעם שתהליך חדש מגיע למערכת, SRTF מחשב למי מבין התהליכים (כולל התהליך החדש) נותר הכי פחות זמן לרוץ, ובוחר את התהליך הזה לריצה.תחת ההנחות החדשות, ניתן להוכיח כי SRTF אופטימלי במדד זמן התגובה הממוצע.בתוספת הנחה כי זמן החלפת הקשר הוא אפסי.מערכות הפעלה - תרגול 515כל התהליכים רצים למשך אותו זמן.כל התהליכים מגיעים באותו זמן (t=0).אם תהליך התחיל לרוץ, אז הוא ירוץ עד לסיומו ללא הפסקות.התהליכים משתמשים רק במעבד ולא מבצעים I/O.זמן הריצה של כל התהליכים ידוע מראש.
מדיניות זימון של תהליךלכל תהליך זמן-אמת יש מדיניות זימון (scheduling policy):SCHED_FIFO או SCHED_RR .נקבעת ע"י המשתמש באמצעות קריאות מערכת sched_setscheduler() .מדיניות הזימון – תשפיע על כמה זמן ריצה כל תהליך יקבל ואופן עבודת התור.מערכות הפעלה - תרגול 535
The exam text, the skills it tests, and the exact slides are already in context.