תהליכים ב- UNIX

‫‪Principles of Structure of‬‬
‫‪Operating Systems‬‬
‫עקרונות מבנה מערכות הפעלה‬
‫מערכת ההפעלה ‪ -UNIX‬סקירה‬
‫מצגת מס' ‪2‬‬
‫תהליכים ב‪UNIX -‬‬
‫היחידה הפעילה ב‪ UNIX-‬היא התהליך‪.‬‬
‫כל תהליך מריץ תוכנית יחידה‪.‬‬
‫מאחר שכל אחד יכול להריץ מספר תהליכים‪ ,‬אזי יתכן מצב בו ירוצו‬
‫תהליכים רבים במקביל‪ ,‬אפילו בזמן שהמשתמש לא מריץ דבר‪,‬‬
‫רצים תהליכי מערכת הנקראים "שדים"‪ .‬תהליכים אלו מתחילים‬
‫לרוץ עם עליית המערכת‪.‬‬
‫• "שד" טיפוסי הוא ‪ CROM‬שרץ פעם בדקה‪ ,‬בודק אם יש עבורו‬
‫עבודה‪ ,‬אם כן מבצע אותה וחוזר לישון‪ ,‬אחרת חוזר לישון עד הפעם‬
‫הבאה שירוץ‪.‬‬
‫• ‪ CROM‬טוב לתזמן זמנים‪ ,‬לשליחת עבודות לשעה מסוימת‬
‫וכדומה‪" .‬שדים" אחרים אחראיים על דואר אלקטרוני‪ ,‬ניהול תור‬
‫של מדפסת‪ ,‬בדיקה האם יש מספר דפים פנויים בזיכרון‪.‬‬
‫עץ תהליכים ב‪UNIX -‬‬
‫לתהליך שממנו נוצר תהליך אחר קוראים תהליך אב‪,‬‬
‫לתהליך החדש קוראים בן‪.‬‬
‫בדרך‪-‬כלל‪ ,‬האב מגדיר או מוריש משאבים ותכונות לבניו‬
‫קבצים פתוחים ניתנים לשיתוף בין האב לבן‪ .‬אם קובץ‬
‫היה פתוח אצל ההורה לפני קריאת ‪ ,FORK‬הוא ימשיך‬
‫להיות פתוח עבור הבן וההורה לאחר מכן‪.‬‬
‫האב יכול להמתין לבנו‪ ,‬לסיים‪ ,‬או להמשיך לרוץ במקביל‪.‬‬
‫בסופו של דבר מאחר שיכולים להיות הרבה ילדים וגם‬
‫להם ילדים נבנה עץ של תהליכים‪.‬‬
‫התהליך ‪INIT‬‬
‫• עם עליית המערכת עולה התהליך ‪ .INIT‬תהליך זה‬
‫קורא מספריית ‪ /ETC/TTYS‬מה מספר המסופים\כניסות‬
‫שיש למערכת‪ .‬ואינפורמציה לגבי כל אחת מהכניסות‪.‬‬
‫לאחר מכן משאיר בן בכל כניסה‪ ,‬שמפעיל את תוכנית‬
‫‪ ,LOGIN‬והולך לישון עד שאחד המסופים ינסה להיכנס‬
‫לעבודה‪.‬‬
‫בכל מסוף מופיע ‪ , LOGIN‬לאחר ה‪ LOGIN -‬נתבקש‬
‫להקיש סיסמא‪ ,‬הסיסמא תיבדק בספריה‬
‫‪ETC/PASSWD/‬‬
‫אם הסיסמא נכונה‪ ,‬ה‪ LOGIN -‬יפעיל את מעטפת‬
‫המשתמש‪.‬‬
‫התהליך ‪INIT‬‬
‫יצירת תהליכים ב‪fork() :UNIX-‬‬
‫• יוצר ומאתחל ‪.PCB‬‬
‫• מיצר מרחב כתובות חדש‪ ,‬ומאתחל‬
‫אותו עם העתק מלא של מרחב‬
‫הכתובות של האב‪.‬‬
‫• מאתחל משאבי גרעין לפי משאבי‬
‫האב (למשל‪ ,‬קבצים פתוחים)‬
‫– באג נפוץ הוא שכיחת סגירת קבצים‬
‫פתוחים של האב אצל הבן‬
‫•‬
‫•‬
‫•‬
‫שם את ה‪ PCB-‬בתור המוכנים‬
‫עכשיו יש שני תהליכים‪ ,‬אשר‬
‫נמצאים באותה נקודה בביצוע אותה‬
‫תוכנית‪.‬‬
‫שני התהליכים חוזרים מה ‪:fork‬‬
‫– הבן‪ ,‬עם ערך ‪0‬‬
‫– האב‪ ,‬עם מספר התהליך (‪ )pid‬של‬
‫הבן‬
‫‪int main(int argc,‬‬
‫)‪char **argv‬‬
‫{‬
‫;)(‪int child_pid = fork‬‬
‫{ )‪if (child_pid == 0‬‬
‫‪printf(“Son of %d is‬‬
‫‪%d\n”,‬‬
‫;))(‪getppid(),getpid‬‬
‫;‪return 0‬‬
‫{ ‪} else‬‬
‫‪printf(“Father of %d is‬‬
‫‪%d\n”,‬‬
‫;))(‪child_pid,getpid‬‬
‫;‪return 0‬‬
‫}‬
‫יצירת תהליכים ב‪fork():UNIX-‬‬
‫כאשר )(‪ fork‬מופעל נעשית פניה לגרעין על מנת שימצא‬
‫מקום פנוי בטבלת התהליכים‪,‬‬
‫אם מוצא אזי‬
‫מעתיק את כל האינפורמציה של ההורה לכניסה של הבן‪.‬‬
‫לאחר מכן מקצה זיכרון לתהליך הבן מעתיק את‬
‫הסגמנטים של האב‪.‬‬
‫ואז תהליך הבן מוכן לרוץ‪.‬‬
‫יצירת תהליכים‬
‫ב ‪ Unix -‬ישנן שתי צורות להריץ תוכניות‪:‬‬
‫הרצה בחזית ‪foreground‬‬
‫>‪<command‬‬
‫• מתבצעת ע"י כתיבת הפקודה‪:‬‬
‫• פקודה המורצת בחזית גורמת ל‪ prompt -‬להיעלם עד לסיום הפקודה ולכן לא נוכל‬
‫להקליד פקודה נוספת כל עוד הפקודה הנוכחית לא הסתיימה‬
‫• בחזית יכולה להתבצע פקודה אחת לכל היותר‬
‫הרצה ברקע ‪background‬‬
‫& >‪<command‬‬
‫• מתבצעת ע"י כתיבת הפקודה בתוספת &‪:‬‬
‫‪>gcc Calc.c -o Calc‬‬
‫הפקודה מורצת בחזית‪.‬‬
‫& ‪>gcc Calc.c -o Calc‬‬
‫>‬
‫הפקודה מורצת ברקע‪.‬‬
‫‪ ‬על מנת לבצע מספר תוכניות בו זמנית יש להריצן ברקע‪.‬‬
‫לאחר תחילת ביצוע פקודה ברקע מופיע הפרומפט וניתן לתת למערכת פקודות נוספות‬
‫שתתבצענה במקביל לפקודה שהורצה ברקע‬
‫ניהול תהליכים‬
‫בעזרת הפקודה ‪ jobs‬ניתן לבדוק אילו תהליכים קיימים ב‪shell-‬‬
‫– סימן ה‪ "+"-‬מייצג את התהליך ה"נוכחי" – התהליך שהוא ברירת המחדל לפקודות‬
‫שנציג בהמשך‬
‫– סימון ה‪ "-"-‬מייצג את ה"יורש" – התהליך שיקבל את סימן ה‪ "+"-‬אחרי שהתהליך‬
‫הנוכחי יסיים את ריצתו‬
‫‪< more forever.c‬‬
‫)(‪main‬‬
‫{‬
‫;)"‪printf("I am going to run forever !!!\n‬‬
‫; )‪while (1‬‬
‫}‬
‫& ‪> forever‬‬
‫‪[1] 587‬‬
‫!!! ‪> I am going to run forever‬‬
‫‪> jobs‬‬
‫‪[1] + Running‬‬
‫‪forever‬‬
‫‪> kill -9 %1‬‬
‫>‬
‫‪[1] Killed‬‬
‫‪forever‬‬
‫‪>jobs‬‬
‫‪[1] + Running cc prog.c‬‬
‫‪[2] - Running troff -me big_doc.roff‬‬
‫פקודות נוספות המאפשרות הצגה של התהליכים‬
‫שקיימים כרגע הן‪ ps :‬ו‪.top-‬‬
‫ניתן למצוא את המידע בקבצי ה‪ man-‬שלהן‬
‫העברת תהליכים לחזית‬
fg [jobIDs]
.‫[ לחזית‬jobIDs] ‫• מעבירה את התהליך הנוכחי או‬
> more try_input.c
main()
{
char str[20];
printf("I shall try to eat something");
scanf("%s" , str);
printf("%s" , str);
}
> try_input&
[1] 828
> I shall try to eat something
[1] + Suspended (tty input) try_input
> jobs
[1] + Suspended (tty input) try_input
> fg %1
try_input
goodies
goodies
>
‫העברת תהליך לרקע‬
bg [jobIDs]
‫[ לרקע‬jobIDs] ‫• מעבירה את התהליך הנוכחי או‬
> jobs
[1] + Suspended
> bg %1
[1] forever &
> jobs
[1] Running
>
forever
forever
‫השעיית תהליך‬
‫ תהליך מושעה ניתן להעביר‬.‫ משעה את התהליך המתבצע כרגע בחזית‬- Ctrl-z
.bg ‫ או‬fg ‫לחזית או לרקע ע"י שימוש בפקודות‬
jobIDs ‫ משעה את‬stop jobIDs ‫הפקודה‬
> nroff -ms report
Ctrl-z
[1] + Suspended
<bg %
nroff
> emacs &
[1] 982
> forever&
[2] 991
> jobs
[1] + Running
emacs
[2] - Running
forever
> stop %2
>
[2] + Suspended (signal) forever
> jobs
[1] - Running
emacs
[2] + Suspended (signal) forever
>
•
•
‫הריגת תהליך‬
‫•‬
‫•‬
‫‪ - Ctrl-c‬הורג את התהליך המתבצע כרגע בחזית‬
‫הפקודה ‪ kill -9 jobID‬הורגת את התהליך ‪.jobID‬‬
‫&‪< forever‬‬
‫‪[1] 660‬‬
‫!!! ‪> I am going to run forever‬‬
‫‪> kill -9 %fo‬‬
‫‪> jobs‬‬
‫>‬
‫• למרות שמה האכזרי‪ ,‬פקודת ‪ kill‬משמשת באופן כללי לשליחת הודעות‪ .‬בפועל‬
‫שתי ההודעות הנפוצות ביותר שאנו שולחים לתהליכים הן "תמות" (‪)SIGTERM‬‬
‫ו"תמות תכף ומייד!" (‪.)SIGKILL‬‬
‫• הפרמטר לפקודת ‪ ,kill‬בנוסף למזהה התהליך‪ ,‬הוא "‪ ,"-n‬כאשר ‪ n‬הוא מספר‬
‫מזהה של הודעה‪ .‬אם לא מוסיפים מספר‪ ,‬ברירת המחדל היא שליחת ההודעה‬
‫שמזוהה עם המספר ‪" – 15‬תמות"‪ .‬ההודעה שמזוהה עם המספר ‪ 9‬היא "תמות‬
‫תכף ומייד!"‪ .‬ההבדל בן שתי ההודעות היא ש"תמות" מאפשרת לתהליך להרוג‬
‫את עצמו בצורה מסודרת (כמו ביצוע סגירה של המחשב על ידי לחיצה על‬
‫הכפתור ‪ shut down‬במערכת ההפעלה) ואפילו להתעלם מההוראה‪ ,‬ואילו‬
‫"תמות תכף ומייד!" הורגת את התהליך תכף ומייד (כמו ביצוע סגירה של המחשב‬
‫על ידי ניתוק מהחשמל)‬
‫קשר בין תהליכים‬
‫‪PIPE .1‬‬
‫ניתן לסנכרן בין התהליכים משום שאם תהליך מנסה לקרוא מצינור‬
‫שלא הגיע ממנו מידע אזי הוא יחסם עד שהמידע יהיה זמין‪.‬‬
‫‪ .2‬פסיקות תוכנה‬
‫• תהליך יכול לשלוח לתהליך אחר ‪ ,SIGNAL‬התהליך המקבל יכול‬
‫להתעלם או לתפוס אותו ולהגדיר מה לעשות אתו‪ ,‬או להרוג את‬
‫התהליך (ברירת מחדל)‪.‬‬
‫• אם הוחלט לתפוס אותו‪ ,‬אזי חייב להגדיר פרוצדורה שנקראת‬
‫‪ .SIGNAL HANDLING‬לאחר סיום הטיפול בסיגנל התהליך‬
‫יחזור לנקודה אחרי הנקודה בה הוא פנה לפונקצית הטיפול‬
‫בפסיקות‪.‬‬
‫• תהליך יכול לשלוח סיגנלים רק לתהליכים הנמצאים יחד עמו ב‪-‬‬
‫‪ GROUP PROCESS‬שכוללים את הוריו וילדיו‪.‬‬
‫‪UNIX Scheduler‬‬
‫המתזמן ב‪UNIX -‬מבוסס על האלגוריתם ‪.multilevel queue‬‬
‫המבנה בנוי בצורה שבתור הראשון נמצאים המשימות בעלות‬
‫העדיפות הגבוהה ביותר (תור זה בנוי לפי משטר עדיפות )‬
‫בשאר התורים בנויים על פי משטר ‪ (R.R‬כאשר גודל ה‬
‫‪ TQ‬משתנה ביניהם )‬
‫‪UNIX Scheduler‬‬
‫תהליך שרץ ב‪ USER MODE -‬מקבל ערך חיובי‪ ,‬תהליך בגרעין מקבל ערך שלילי‪( .‬ערך שלילי‬
‫בעל עדיפות גבוהה יותר‪ ) .‬תהליך יכול לרוץ יחידת זמן אחת‪ ,‬או עד שהוא נחסם‪ .‬בכל ‪CLOCK‬‬
‫מורדת עדיפות לתהליך ב‪ .1 -‬ואז הוא עובר לתור בעל עדיפות נמוכה יותר‪.‬‬
‫חישוב העדיפות בכל פעם נעשית בצורה הבאה‪:‬‬
‫‪priority = CPU_usage + nice + base‬‬
‫כאשר ‪:‬‬
‫• ‪= CPU_usage‬מייצגת את המספר הממוצע של תקתוקי השעון בכל שנייה‬
‫שהייתה התהליך במהלך בעבר מספר שניות‪.‬‬
‫• ‪ =NICE‬הוא ערך בין ‪ -20‬ל‪( 20 -‬ברירת המחדל ‪.)0‬‬
‫קריאת מערכת ‪NICE‬יכולה לשמש כדי להגדיר ערך זה ‪0-20‬‬
‫‪ =Base‬הוא פרמטר מערכת בקוד המקור ‪UNIX‬‬
‫•‬
‫מתזמן ב ‪ UNIX‬מכריח את ה ‪CPU‬לטפל בעדיפות בתהליך החוזר‬
‫מחסימה עקב פעולת ‪ I/O‬כדי לסיים את התהליך ע"י העברת התהליך‬
‫לתור בעל עדיפות הגבוהה ביותר ‪.‬‬
‫יישום תהליכים‬
‫• לכל תהליך יש חלק שנקרא ‪ USER‬וחלק שנקרא‬
‫‪.KERNEL‬‬
‫חלק הגרעין מתחיל לפעול רק שמתרחשת קריאת‬
‫מערכת‪.‬‬
‫לגרעין יש מחסנית ומונה‪ ,‬והוא מכיל שני מבנים‬
‫השייכים לתהליך‪:‬‬
‫‪PROCESS TABLE‬‬
‫‪USER STRUCTURE.‬‬
‫‪PROCESS TABLE‬‬
‫‪ PROCESS TABLE‬קיימת כל הזמן ומכילה אינפורמציה על כל‬
‫התהליכים‪ ,‬כולל אלו שלא נמצאם כרגע בזיכרון‪.‬‬
‫טבלת התהליכים מכילה את הקטגוריות הבאות‪:‬‬
‫א‪- SCHEDULING PARAMETERS .‬עדיפות‪ ,‬זמן ‪ CPU‬זמן‬
‫שינה‪.‬‬
‫ב‪ - MEMORY IMAGE .‬מצביעים ל‪STACK ,DATA , TEXT-‬‬
‫‪.SEGMENT‬‬
‫ג‪ .‬סיגנלים – אלו סיגנלים התקבלו‪ ,‬אלו חסומים‪ ,‬מאלו מתעלמים ואלו‬
‫נשלחו‪.‬‬
‫ד‪ , MISCELLANEOUS .‬שונות – מצב נוכחי של תהליך‪ ,‬אירועים‬
‫שממתינים להם אם יש‪ ,‬הזמן הנותר לסיום‪ PID ,PID ,‬של הורה‪,‬‬
‫זיהוי המשתמש וקבוצת המשתמש‪.‬‬
‫‪USER STRUCTURE‬‬
‫מכיל אינפורמציה שלא זקוקים לה כשהתהליך לא‬
‫בזיכרון‪.‬‬
‫המידע הנמצא ב‪ USER STRUCTURE -‬הוא‪:‬‬
‫א‪ .‬רגיסטרים – שמירת ערך האוגרים‪.‬‬
‫ב‪ .‬מצב קריאת מערכת – מידע על קריאות המערכת כולל פרמטרים‬
‫ותוצאה‪.‬‬
‫ג‪– FILE DESCRIPTOR TABLE .‬כאשר מתרחשת קריאת‬
‫מערכת‪ ,‬מתקבל מידע לגבי קריאת המערכת המשמש כאינדקס‬
‫לטבלה הזו‪ ,‬וזאת כדי לאחסן את ה‪ I-NODE -‬הקשור לקובץ‪.‬‬
‫ד‪ – ACCOUNTING.‬מצביע לטבלה המכילה מידע על המשתמש‬
‫וזמן ‪ CPU‬של תהליך‪.‬‬
‫ה‪ .‬מחסנית הגרעין – מכיל מידע לשימוש הגרעין של התהליך‪.‬‬
‫שאלת מה"ט בנושא תהליכים‬
‫במערכת ‪ UNIX‬ניתן להריץ מס' תוכניות בו זמנית ‪.‬‬
‫כיצד ניתן להורות למערכת להריץ שתי עבודות בו‬
‫זמנית ( אחת מהן רצה ברקע ) ‪.‬‬
‫מה המנגנון ב‪ UNIX‬שבאמצעותו ניתן לתזמן‬
‫תוכניות שונות ‪.‬‬
‫פרט תשובתך‬
‫שאלת מה"ט בנושא תהליכים‬
‫מהו ה ‪ PROCESS‬הראשון שעולה ב ‪? UNIX‬‬
‫מה תפקידו ?‬
‫מה קורה עם "הורגים" (‪ ) KILL‬לתהליך זה ?‬