מערכות הפעלה

Download Report

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

‫מערכות הפעלה‬
‫תרגול ‪ – 4‬ניהול תהליכים‪ ,‬מבני נתונים למימוש‬
‫תהליכים‬
‫מה בתכנית?‬
‫‪ ‬ניהול תהליכים‬
‫‪ ‬מימוש תהליכים ב‪XINU-‬‬
‫‪ ‬טבלת תהליכים‬
‫‪ ‬מימוש תורי תהליכים‬
‫‪ ‬תרגילים‬
‫‪2‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫ניהול תהליכים‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪3‬‬
‫המעבד מריץ את כל התהליכים אך בכל רגע נתון הוא‬
‫מריץ תהליך בודד‬
‫התהליך המורץ במעבד נקרא תהליך נוכחי ( ‪current‬‬
‫‪)process‬‬
‫תהליכים אחרים מחכים לביצוע במעבד‪ ,‬או מחכים‬
‫לקבלת משאב אחר‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫ניהול תהליכים‬
‫‪ ‬מערכת ההפעלה אחראית על כך שבכל רגע ורגע‬
‫יהיה תהליך אחד מוגדר כתהליך הנוכחי‬
‫‪ ‬במידה והתהליך מוותר על מעמדו כתהליך הנוכחי‬
‫או שמערכת ההפעלה מחליטה להחליפו‪ ,‬עליה‬
‫לבחור תהליך אחר שיחליף אותו‬
‫‪4‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫ניהול תהליכים‬
‫‪‬‬
‫האלגוריתם המחליט האם להחליף את התהליך הנוכחי‬
‫ומי התהליך שיחליפו נקרא זמן (‪)Scheduler‬‬
‫‪‬‬
‫בזמן החלפת התהליך הנוכחי יש לשמור את ההקשר‬
‫שלו (‪( )context‬הכולל את ערכי הרגיסטרים שונים) כדי‬
‫שניתן יהיה לשחזר אותו בזמן החזרתו לביצוע (החלפת‬
‫הקשר‪)Context Switching ,‬‬
‫‪5‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מדיניות הזימון‬
‫‪‬‬
‫‪‬‬
‫התהליך הנוכחי נבחר בין תהליכים המחכים למעבד‬
‫קיימות כמה שיטות לבחירת התהליך הנוכחי‪:‬‬
‫‪ ‬מדיניות ‪FIFO‬‬
‫‪ ‬בחירה סדרתית (‪)Round-Robin‬‬
‫‪ ‬בחירה לפי עדיפות‬
‫‪ ‬בחירה לפי זמן ריצה‬
‫‪6‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫)‪First Come First Serve (or FIFO‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫במקור‪ ,‬תהליך אחד משתמש במעבד עד לסיומו‬
‫כיום‪ ,‬תהליך משתמש במעבד עד שנחסם בהמתנה‬
‫למאורע כלשהו‬
‫מדיניות ללא הפקעה (‪)non-preemptive‬‬
‫תהליכים קצרים "נתקעים" אחרי תהליכים ארוכים =>‬
‫תהליכים קצרים נמצאים הרבה זמן בתור המוכנים‪ ,‬יחסית‬
‫לזמן החישוב שהם צורכים‬
‫‪7‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫‪Round-Robin‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪8‬‬
‫כל תהליך מקבל את המעבד לפרק זמן קצוב‪ ,‬ולאחריו‬
‫הוא מוחלף באחר אף אם לא סיים‪ .‬ההחלפה נעשית לפי‬
‫סדר קבוע (‪)Round-Robin‬‬
‫חלוקת זמן בין התהליכים השונים הוגנת‬
‫נוכחי‬
‫דוגמה‪:‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מדיניות הזימון‬
‫‪‬‬
‫‪‬‬
‫לפי עדיפות‪ :‬לכל תהליך משוייך מספר עדיפות‪ .‬התהליך‬
‫בעל עדיפות גבוהה ביותר המחכה למעבד הופך לתהליך‬
‫הנוכחי‬
‫סדר העדיפויות‪:‬‬
‫‪13‬‬
‫‪9‬‬
‫‪10‬‬
‫‪9‬‬
‫‪8‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫‪6‬‬
‫‪1‬‬
‫אפריל ‪15‬‬
‫מדיניות הזימון לפי עדיפות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪10‬‬
‫התהליך הנוכחי יאבד את המעבד רק אם תהליך בעל‬
‫עדיפות גבוהה יותר ידרוש אותו‪ ,‬או שהנוכחי יוותר עליו‬
‫אם תהליך בעל עדיפות גבוהה יותר לא ישחרר את‬
‫המעבד‪ ,‬תהליכים בעלי עדיפות נמוכה יותר לא יתבצעו‬
‫קיימות מ"ה בהן תהליך שמתבצע מאבד את עדיפותו עם‬
‫הזמן‪ ,‬ותהליך שמחכה משפר את עדיפותו כדי לאפשר‬
‫"צדק" גדול יותר בחלוקת משאב המעבד‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מדיניות הזימון – היישום ב‪XINU-‬‬
‫‪‬‬
‫‪ XINU‬משתמשת בשיטת העדיפויות כאשר בין‬
‫התהליכים באותה עדיפות מתבצע ‪Round-Robin‬‬
‫‪‬‬
‫העדיפות של תהליך נקבעת בזמן יצירתו‪ ,‬אך ניתנת‬
‫לשינוי בכל עת‪.‬‬
‫‪11‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫ דיאגרמת מצבים‬- ‫תהליך‬
send
receive
RECEIVING
wait
signal
WAITING
sleep
wake up
SLEEPING
resched
resched
CURRENT
READY
suspend
SUSPENDED
suspend
resume
Create
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
12
‫טבלת תהליכים‬
‫‪ ‬קיימת טבלת תהליכים‪ ,‬המיוצגת כוקטור של‬
‫רשומות‪ ,‬בה כל רשומה מייצגת הקשר של תהליך‪,‬‬
‫ולכל תהליך מוקצת רשומה‬
‫‪ ‬רשומה מכילה את המידע על מצב התהליך ואת כל‬
‫המידע על הקשר התהליך הדרוש להפעלתו‬
‫‪ ‬קיימים מספר משתנים המייצגים את מצב התהליך‬
‫או שמציינים שתהליך מחכה למשאב כלשהו‬
‫‪13‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫טבלת תהליכים‬
‫‪ ‬האינדקס בטבלת התהליכים משמש כמזהה של‬
‫התהליך (‪)pid – process identifier‬‬
‫‪ ‬המזהה של התהליך הנוכחי שמור במשתנה נפרד‬
‫המאפשר התיחסות לתהליך הנוכחי מקוד מ"ה‬
‫‪ ‬התהליכים המחכים למעבד שמורים בתור דו‪-‬כווני‬
‫על פי עדיפותם‪ .‬תור זה נקרא ‪ready queue‬‬
‫ומבוצע על ידי ‪rdyhead, rdytail‬‬
‫‪14‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
proc.h - ‫טבלת תהליכים‬
#define NULLPROC
extern
extern
extern
extern
15 ‫אפריל‬
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 ‫ תרגול‬- ‫מערכות הפעלה‬
*/
*/
*/
15
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
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
};
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
16
proc.h - ‫טבלת תהליכים‬
#define NPROC
30
/* process state constants */
#define
#define
#define
#define
#define
#define
#define
15 ‫אפריל‬
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 ‫ תרגול‬- ‫מערכות הפעלה‬
17
‫תהליך ה‪NULL-‬‬
‫מה עושה מ"ה כאשר אין תהליך הדורש מעבד?‬
‫‪ ‬אחת הדרכים האפשריות היא לתת לזמן לבצע‬
‫לולאה ולחכות עד שתהליך כלשהו יהיה מוכן לחזור‬
‫לביצוע אך לשם כך שקוד הזמן יהיה מורכב יותר‬
‫‪ ‬דרך מועדפת הינה ליצור תהליך שתמיד יהיה מוכן‬
‫לחישוב‬
‫‪18‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫תהליך ה‪NULL-‬‬
‫‪‬‬
‫תהליך זה נקרא ‪ NULL process‬ובנוי כלולאה אינסופית‬
‫מהצורה‬
‫;‪While (TRUE) /* Do nothing */‬‬
‫‪‬‬
‫תהליך ה‪ NULL-‬יקבל את העדיפות המזערית האפשרית‬
‫ולכן יהפך לנוכחי רק כאשר אין אף תהליך אחר שדורש‬
‫את המעבד‬
‫המזהה של תהליך זה הוא ‪0‬‬
‫‪‬‬
‫‪19‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫רשימות תהליכים ב‪XINU-‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪20‬‬
‫במהלך הריצה‪ ,‬בכל רגע‪ ,‬חלק ניכר מתהליכים נמצאים‬
‫במצב המתנה למשאבים (‪ ,CPU‬קלט‪ ,‬הודעה וכו')‬
‫מכיוון שמספר תהליכים עלולים להמתין לאותו משאב יש‬
‫לנהל תור המתנה‬
‫כלל‪ :‬התהליך יכול להופיע בכל זמן נתון בתור אחד‬
‫מספר התהליכים והתורים השונים הוא סופי‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מימוש הרשימות‬
‫‪ ‬בעיה‪ :‬הרשימות הנחוצים עבור המשאבים השונים הם‬
‫מגוונים (‪, FIFO‬לפי עדיפות‪ ,‬תור הפרשים)‬
‫עובדה זו מקשה על ניהול מערכת הרשימות‬
‫‪‬‬
‫‪21‬‬
‫פתרון‪ :‬מבנה אחיד לכל הרשימות שמספק את כל מגוון‬
‫הדרישות ומאפשר אחידות בטיפול‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מבנה רשומה‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪ - qprev‬מצביע האיבר הבא‬
‫‪ - qnext‬מצביע האיבר הקודם‬
‫‪ - qkey‬מפתח‪ ,‬עדיפות של התהליך במקרה של תור ה‪-‬‬
‫‪ready‬‬
‫‪tail‬‬
‫^‬
‫‪22‬‬
‫‪head‬‬
‫‪next‬‬
‫‪MAXINT‬‬
‫‪prev‬‬
‫‪next‬‬
‫‪KEY‬‬
‫‪prev‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫‪MININT‬‬
‫^‬
‫אפריל ‪15‬‬
‫הגדרת תור – ‪q.h‬‬
‫מבנה רשומה‪:‬‬
‫{ ‪struct qent‬‬
‫;‪int qkey‬‬
‫;‪int qnext‬‬
‫;‪int qprev‬‬
‫;}‬
‫‪23‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫תורים ב‪XINU-‬‬
‫‪‬‬
‫תור התהליכים המחכים למעבד‬
‫‪ ‬תור עדיפויות‪ ,‬הכנסה לפי מפתח – עדיפות‬
‫‪ ‬בתור עדיפויות התהליכים מסודרים בסדר עולה בכיוון ראש => זנב‬
‫‪ ‬הוצאה – איבר אחרון‬
‫‪‬‬
‫תור התהליכים המחכים לסמפור – ‪FIFO‬‬
‫‪ ‬הוצאה – מראש התור‬
‫‪‬‬
‫תור הרדומים – תור ההפרשים‬
‫‪24‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫מימוש רשימה בעזרת מערך‬
‫‪Prev‬‬
‫‪Next‬‬
‫‪Key‬‬
‫‪3‬‬
‫‪33‬‬
‫‪25‬‬
‫‪0‬‬
‫‪14‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪...‬‬
‫‪32‬‬
‫‪3‬‬
‫‪NPROC‬‬
‫‪NPROC-1‬‬
‫איבר קודם‬
‫איבר הבא‬
‫‪...‬‬
‫‪NPROC‬‬
‫‪2NSEM+4‬‬
‫‪25‬‬
‫‪-1‬‬
‫‪3‬‬
‫‪MININT‬‬
‫‪Head=32‬‬
‫‪1‬‬
‫‪-1‬‬
‫‪MAXINT‬‬
‫‪Tail=33‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
q.h – ‫הגדרת תור‬
Inline list
manipulation
procedures
extern struct qent q[];
#define isempty(list) (q[(list)].qnext >= NPROC)
#define nonempty(list) (q[(list)].qnext < NPROC)
#define firstkey(list) (q[q[(list)].qnext].qkey)
#define lastkey(tail) (q[q[(tail)].qprev].qkey)
#define firstid(list) (q[(list)].qnext)
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
26
‫פונקציות לטיפול ברשימות‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪27‬‬
‫‪ enqueue‬הכנסת איבר לסוף הרשימה‬
‫‪ dequeue‬ניתוק איבר מהרשימה והחזרת האינדקס שלו‬
‫‪ insert‬הכנסת תהליך לרשימה לפי ערכו של ‪key‬‬
‫‪ getfirst‬הסרת התהליך הראשון ברשימה והחזרת‬
‫האינדקס‬
‫‪ getlast‬הסרת התהליך האחרון ברשימה והחזרת‬
‫האינדקס‬
‫‪ newqueue‬איתחול רשימה חדשה במבנה ה‪q-‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
queue.c – ‫הוצאה מתור‬
#include <conf.h>
#include <kernel.h>
#include <q.h>
int dequeue(item)
int item;
{
struct qent
*mptr; /* q entry for item */
mptr = &q[item];
q[mptr->qprev].qnext = mptr->qnext;
q[mptr->qnext].qprev = mptr->qprev;
return(item);
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
28
insert.c – ‫הכנסה לפי מפתח‬
#include <conf.h>
#include <kernel.h>
#include <q.h>
int insert(proc, head, key)
int proc; /* process to insert
*/
int head; /* q index of head of list
*/
int key; /* key to use for this process */
{
int
next;
/* runs through list */
int
prev;
next = q[head].qnext;
while (q[next].qkey < key) /* tail key is MAXINT */
next = q[next].qnext;
q[proc].qnext = next;
q[proc].qprev = prev = q[next].qprev;
q[proc].qkey = key;
q[prev].qnext = proc;
q[next].qprev = proc;
return(OK);
15 ‫אפריל‬
}
2 ‫ תרגול‬- ‫מערכות הפעלה‬
29
queue.c – ‫הוספה לסוף התור‬
#include <conf.h>
#include <kernel.h>
#include <q.h>
int enqueue(item, tail)
int item;
int tail;
{
struct
qent
struct
qent
*tptr; /* tail entry */
*mptr; /* item entry */
tptr = &q[tail];
mptr = &q[item];
mptr->qnext = tail;
mptr->qprev = tptr->qprev;
q[tptr->qprev].qnext = item;
tptr->qprev = item;
return(item);
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
30
– ‫הסרת התהליך הראשון ברשימה‬
getitem.c
#include <conf.h>
#include <kernel.h>
#include <q.h>
int
int
{
getfirst(head)
head; /* q index of head of list */
int
proc; /* first process on the list
if ((proc=q[head].qnext) < NPROC)
return( dequeue(proc) );
else
return(EMPTY);
*/
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
31
– ‫הסרת התהליך האחרון ברשימה‬
getitem.c
#include <conf.h>
#include <kernel.h>
#include <q.h>
int
int
{
getlast(tail)
tail; /* q index of tail of list */
int proc;
/* last process on the list */
if ((proc=q[tail].qprev) < NPROC)
return( dequeue(proc) );
else
return(EMPTY);
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
32
– ‫איתחול רשימה חדשה‬
newqueue.c
int
{
newqueue()
struct
struct
int
qent
*hptr;
qent
*tptr;
hindex, tindex;
/* address of new list head */
/* address of new list tail */
/* head and tail indexes
*/
/* nextqueue is global variable
hptr = &q[ hindex=nextqueue++ ];
/* giving next used q pos. */
tptr = &q[ tindex=nextqueue++ ];
hptr->qnext = tindex;
hptr->qprev = EMPTY;
hptr->qkey = MININT;
tptr->qnext = EMPTY;
tptr->qprev = hindex;
tptr->qkey = MAXINT;
return(hindex);
15 ‫אפריל‬
}
2 ‫ תרגול‬- ‫מערכות הפעלה‬
*/
33
‫טבלת תהליכים ‪ /‬תורים‬
‫יישום התורים של התהליכים מתבצע על ידי פונקציות‬
‫ניהול תורים לכן‪:‬‬
‫‪ ‬אין בטבלת תהליכים מצביעים על סדר התורים‬
‫‪ ‬ניהול התורים נעשה בטבלת התורים (‪)q‬‬
‫‪ ‬לכל תהליך משוייכת רשומה בטבלת תהליכים וכן‬
‫בטבלת התורים‬
‫‪34‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
‫טבלת תהליכים ‪ /‬תורים‬
‫‪ ‬בטבלת התורים יש יותר רשומות מטבלת‬
‫התהליכים‪ NPROC.‬רשומות ראשונות בטבלת‬
‫התורים משוייכות לתהליכים המקבילים בטבלת‬
‫התהליכים‪.‬‬
‫‪ ‬שאר הרשומות בטבלת התורים משמשות‬
‫כראשי‪/‬זנבות תורים שונים (‪, Ready‬סמפורים‪ ,‬ו‪-‬‬
‫‪)sleeping‬‬
‫‪35‬‬
‫מערכות הפעלה ‪ -‬תרגול ‪2‬‬
‫אפריל ‪15‬‬
3 ‫תרגיל‬
‫ כפי שהוא נראה ברגע‬Q ‫יש למלא את המבנה של‬
/**/ -‫שהתכנית הגיע אל הנקודה המסומנת ב‬
#include <kernel.h>
extern SYSCALL sleep(), wait();
int nop();
xmain() {
int sem = screate(1);
resume(create(sleep,
INITSTK, 20, “pr1”, 1, 25));
resume(create(wait,
INITSTK, 22, “pr2”, 1, sem));
resume(create(wait,
INITSTK, 24, “pr3”, 1, sem));
resume(create(sleep,
INITSTK, 21, “pr4”, 1, 10));
resume(create(nop,
INITSTK, 20, “pr5”, 0));
resume(create(sleep,
INITSTK, 20, “pr6”, 1, 30));
resume(create(wait,
INITSTK, 20, “pr7”, 1, sem));
resume(create(nop,
INITSTK, 20, “pr8”, 0));
create(sleep, INITSTK, 33, “pr9”, 1, 44);
/**/
nop();
}
15 ‫אפריל‬
2 ‫ תרגול‬- ‫מערכות הפעלה‬
nop()
{
while(1){};
}
36
3 ‫תרגיל‬
pid
key
next
prev
proc/list
name
…
…
…
…
…
SEM
pr3
pr7
SLEEP
pr4 (10)
pr1 (15)
1
READY
15 ‫אפריל‬
pr5 (20)
pr6 (5)
2
pr8 (20)
2 ‫ תרגול‬- ‫מערכות הפעלה‬
37