מערכות הפעלה – המכללה האקדמית תל אביב – יפו סמסטר א ,תשע"ז מרצה :כרמי מרימוביץ .מתרגל :צבי מלמד תרגיל בית מספר #2 הוראות כלליות בתרגיל הזה שאלה אחת בסביבת ,XV6שכוללת שתי משימות: .1מימוש סמפורים בXV6 - .2כתיבת תכנית בדיקה שמשתמשת בסמפורים האלו. הגשה עד עד ליום רביעי 11/1/17בחצות הוראות ההגשה המפורטות נמצאות באתר. הסביבה הקובעת להרצת התרגילים היא סביבת BOCHS +CYGWINבמעבדה יש לבדוק ולהריץ את התרגיל כאשר האמולטור עובד לפחות עם 2מעבדים .מומלץ לבדוק גם עם 4מעבדים. (אתם מגדירים את זה בקובץ ,bochsrcחפשו אחר המילה ”…= .)“cpu: count הבהרה :אתם יכולים לפתח ולפתור את התרגילים בסביבה הנוחה לכם .אבל ,לפני ההגשה ,חובתכם לוודא שהתרגילים רצים בסביבה הפורמלית-סטנדרטית. הנחיות לגבי עבודת צוות הגשת התרגיל ביחידים היזהרו מהעתקות! ראו הוזהרתם. למרות האמור בסעיף הקודם – מותר ששני תלמידים (לכל היותר!) יעבדו על התרגיל ביחד .במקרה כזה ,יהיה להם קוד זהה (מן הסתם) .במקרה כזה חובה עליהם לציין בתחילת קובץ ה READ_MEאת השמות של שניהם כולל ת.ז .של שניהם!). ~~1 שאלה - #1משימה א' :מימוש סמפורים ב XV6 עליכם לממש קריאות מערכת שמממשת סמפורים על פי ה APIשמוגדר להלן .עליכם לתעד את אופן מימוש הסמפורים ואת תכנית המשתמש שכתבתם .את התיעוד שצריך להיות קצר כתבו בקובץ טקסט שנקרא READ_ME.txtאו .READ_ME.PDF תיאור כללי: התנהגות הסמפורים כאן ,דיי דומה (אבל לא זהה) להתנהגות הסמפורים שמתוארת ב man 7 sem_overview בסביבת לינוקס. במובנים מסוימים הטיפול בסמפורים יהיה דומה לטיפול ב – file-descriptorsכלומר ,יהיה לנו מערך של OSEM (בדומה למערך של .)OFILEבקשה לפתיחת סמפור תחזיר – SDכלומר ,semaphore-descriptorובהמשך, קריאות מערכת יקבלו את ה SDהזה כארגומנט ,ועל פיו הקרנל יודע באיזה סמפור מדובר. לסמפור יש ערך התחלתי וערך מקסימלי שאליו הוא יכול להגיע (כולל) אבל לא לעבור אותו. פתיחת סמפור מתבצעת ע"י .sem_openאם סמפור בשם הזה כבר קיים ,אזי מתעלמים מהארגומנטים של ערכי האיתחול והערך המקסימלי .אם הוא לא קיים עדיין במערכת ,אזי יוצרים סמפור כזה ,ומאתחלים אותו בערכים .init and maxVal הפונקציה sem_closeסוגרת את הסמפור ,אבל איננה משחררת את המשאב .כלומר ,גם אם כל התהליכים סגרו את הסמפור sem_xשהם פתחו ,הסמפור sem_xנשאר במערכת ,ואיננו נמחק. הפונקציה sem_unlinkמוחקת את הסמפור מהמערכת .יתכן מצב שמריצים את הפונקציה הזאת ,אבל ישנם תהליכים שעדיין מצביעים לסמפור הזה .במקרה כזה ,הפעולה הזאת תיחסם ,עד שאחרון הסמפורים ייסגר ( g”h הקריאה )( sem_closeאו ע"י ביצוע .)exitבמקרה כזה הפעולה הזאת תתבצע כאשר יקרה ה close() -האחרון על הסמפור המדובר( .עדכון בדרישה .)1.1.17 הפונקציות )( sem_wait() and sem_postפועלות כרגיל וכמצופה. הפונקציה sem_try_waitפועלת בדומה למקבילה לה בלינוקס – היא מנסה לבצע WAITאבל איננה נחסמת אם ערך הסמפור הוא ( 0כמובן שבאמצעות הערך המוחזר המשתמש יכול לדעת מה קרה למעשה). הפונקציה sem_get_valueמחזירה את ערכו הנוכחי של הסמפור וכן את ה maxValשלו. פרוטוטייפ הפונקציות: ;)sem_open(char *name, int init, int maxVal ;)sem_close(int sd ;)sem_wait(int sd ;)sem_try_wait(int sd ;)sem_signal(int sd ;)sem_get_value(int sd, int *val sem_unlink(char *name); // שימו לב לתיקון ההגדרה!! ~~2 int int int int int int int :להלן תיאור ההתנהגות הדרושה מכל אחת מהפונקציות int sem_open(char *name, int init, int maxVal) Open a semaphore and return SD (semaphore-descriptor) to it. . אליוSD והחזר את ה,פתח סמפור הסמפור הזה כבר מוגדר (קיים) או שהוא:כאשר תהליך מבצע קריאה לפונקציה הזאת – יכולים להיות שני מקרים .עדיין איננו קיים במערכת , אם סמפור כזה איננו קיים במערכת.init and maxVal מתעלמים מערכי,אם סמפור כזה קיים כבר במערכת . ומאתחלים את הערכים שלו בהתאם לארגומנטים של הפונקציה,אזי יוצרים אותו - הכניסה המתאימה במערך ה, המתאים (כלומרSD כאשר הפונקציה מצליחה היא מחזירה את ה:ערך מוחזר ואין אפשרות ליצור, הסתיימה מכסת הסמפורים במערכת, אם הפונקציה נכשלה מסיבה כלשהי (למשל.)OSEM .-1 עוד סמפור) אזי היא תחזיר :בהקשר למגבלת המשאבים שימו לב להערה הבאה a) A kernel constant NOSEM (Number of Open Sem) limits the number of open semaphores per process, similar to the NOFILE. Of course, if the call might result in exceeding NOSEM (per this process), the call fails and returns -1. b) A kernel constant NSEM limits the total number of active semaphores in the system. This is similar to NFILE. c) The length of semaphore-name <= 6 . int sem_close(int sd); a) This call closes an open semaphore. Error code of -1 is returned if sd is index of non-valid entry in the process semaphore table. b) If this is the last reference to the semaphore, then we check if there’s a pending sem_unlink wanting to destroy the semaphore. Note: the semaphore as a system wide resource is not destroyed, just like when you close a file, it is not erased from the disk. (1.1.17 notice, there was a slight change to the requirement here from the original one). int sem_wait(int sd); This is standard wait operation of semaphores. a) if sem > 0 then this call decrements the value of the semaphore. Otherwise the process is put to sleep until this condition is true. b) The process wakeups when the decrement is possible, and checks again the condition in (a). int sem_trywait(int sd); ~3~ This call tries to decrement the value of the semaphore, provided it does not become negative. If this is possible, the call returns 0 (success). If this is not possible, the call returns -1 (failure), but the process is NOT suspended. אזי סימן,0 אם הקריאה החזירה. הקריאה הזאת איננה גורמת לתהליך להיחסם, בכל מקרה,במלים אחרות אזי זה סימן-1 אם הקריאה מחזירה.)שהסמפור הוקטן באחד (כלומר היה בערך גדול מאפס בזמן שערכון נדגם .)שהסמפור לא הוקטן באחד (כלומר היה בערך אפס בזמן שערכו נדגם int sem_signal(int sd); This is standard ‘signal’ (or ‘post’) operation of semaphores. a) The value of the semaphore is incremented. b) wakeup other processes who might be waiting on this semaphore. c) If sd is not an open semaphore entry, the call returns -1. d) If the value of the semaphore is already at maxVal (as set in sem_open) then the value is not incremented, and the call returns failure code of -2. int sem_get_value(int sd, int *val, int* maxVal); . את ערכו המקסימליmaxVal ובמשתנה, את ערכו הנוכחי של הסמפורval הקריאה הזאת מחזירה במשתנה מצביע על כניסה מאופסתsd אם משהו לא תקין (למשל-1 - ו, אם הכל תקין0 הערך המוחזר של הקריאה הוא .)OSEM בטבלת ה int sem_unlink(char *name); .שימו לב לשינוי ההגדרה !הקריאה הזאת מוחקת את הסמפור מהמערכת אם תהליכים כלשהם מצביעים אל,הסמפור נמחק מהקרנל רק כאשר אין עוד מצביעים אל הסמפור! כלומר זהו תיקון לדרישה:1.1.2017( ! אזי הקריאה הזאת נחסמת עד שכולם סגרו את הסמפורים שלהם.הסמפור בזמן, על הסמפורOPEN אין למנוע מתהליכים לבצע פעולות.) בגירסה הראשונה של הדרישות,הקודמת .sem_unlink שתהליך אחד (או יותר) ממתינים לביצוע init and יוצר סמפור חדש במערכת מאתחל את ערכי, מיד לאחר הפעולה הזאתsem_open תהליך שיבצע . שלוmaxVal Suggestions Don’t invent the wheel, and don’t invent the semaphore. Refer to handling of files (ofile and ftable) to get ideas on ways to implement things. Add a global variable stable (semaphore table) to the system, defined as follows: struct { struct spinlock gslock; //global semaphore lock struct { ~4~ struct spinlock sslock; // single semaphore lock ..... ..... ;]} sem[NSEM ;} stable Use gslock for sem_open and sem_close and sem_unlink. Use sslock for sem_wait, sem_trywait and sem_signal. Consider the fork() – child should inherit all opened semaphores from the parent. Consider the implications of exit(). Consider the implication of exec() – unlike fork() - the new program does NOT get the semaphores. (הערה :זאת איננה ההתנהגות המצופה "בחיים האמיתיים" .כלומר ,בד"כ כשעושים .EXECניתן לצפות שהתכנית החדשה תקבל את הסמפורים של התכנית הישנה ,בדיוק כשם שהיא מקבלת את הקבצים הפתוחים .ההגדרה השונה כאן היא למטרות התרגיל הזה). הערות ודגשים א. ב. שני הערכים NSEMו NOSEM -יוגדרו בקובץ .param.hהתכנית שלכם צריכה לעבוד עם ערכים כלשהם – כלומר ,יתכן שהבודק יריץ את התרגיל שלכם עם קובץ param.hמשלו -אותם שמות ,אבל ערכים אחרים .התרגיל שלכם צריך להתקמפל ולרוץ באופן תקין .כמובן ,שאי הקפדה על דיוק בכתיבת השמות תגרום לכך שהקומפילציה תיפול. קובץ ה Makefileשלכם צריך להכיל כניסה בהגדרה של UPROGSבשם testשמתאימה לקובץ עם תכנית משתמש .test.cהבודק יריץ את התרגיל שלכם עם קובץ test.cמשלו ,והתרגיל צריך להתקמפל "חלק". שאלה - #1משימה ב' – תכנית משתמש שעובדת עם סמפורים. בתכנית זאת נדמה פעולת יצרן-צרכן ,שכותבים לחוצץ משותף .מכיוון שאין לנו חוצץ משותף ,לא באמת נכתוב הודעות לחוצץ ,ובמקום זאת נכתוב אותן לפלט הסטנדרטי. המספר המקסימלי של ההודעות כביכול בחוצץ הוא .MAX_MSGכלומר ,אם למשל MAX_MSG ==3אזי אנחנו לא מצפים לראות בפלט יותר משלוש הודעות על "הוספה" (כלומר הודעות מ ,PRODהיצרן) מבלי שיש הודעות על "הסרה" (הדעות שיגיעו מ – CONS -הצרכן). א. תהליך בשם ( prodקיצור של )producerמייצר הודעות .כל הודעה נוצרת ע"י קריאה לפונקציה write_prod_msgשהפרוטוטייפ שלה הוא: ;()void write_prod_msg ~~5 ב. תהליך בשם ( consקיצור של )consumerקורא הודעות .אנו מדמים קריאת הודעה ע"י קריאה לפונקציה write_cons_msgשהפרוטוטייפ שלה הוא: ;()void write_cons_msg ג. תכנית בשם ( pcקיצור של )producer-consumerמקבלת 3עד 4ארגומנטים: )1 )2 )3 )4 כמה תהליכים PRODלייצר כמה תהליכים CONSלייצר כמה הודעות מייצר כ"א מה PROD הארגומנט הרביעי הוא אופציונלי :אם הוא ניתן ,אז זה שם קובץ ,שצריך לעשות אליו REDIRECTIONלפלט הסטנדרטי של כל התהליכים PRODו.CONS - התכנית PCמתנהגת באופן הבא: א .היא יוצרת תהליכים PRODו CONS -במספר הדרוש ב .כותבת למסך הודעה בסגנון ******************* PARENT pid = 5 created all children ההודעה הזאת נוצרת ע"י קריאה לפונקציה )(.write_parent_msg הפעולה של התהליכים cons and prodמתחילה רק לאחר שהתהליך ההורה סיים להדפיס את ההודעה שלו. כמובן ,שעליכם לוודא שדרישות הסנכרון מתקיימות: הבנים לא מתחילים לפעול לפני שתהליך האב יצר את כל הבנים. תהליכי PRODלא מייצרים יותר מאשר MAX_MSGהודעות שלא נצרכו תהליכים CONSלא צורכים הודעה לפני שהיא נוצרה כל תהליך PRODיודע כמה הודעות הוא צריך לייצר – זה הארגומנט השלישי בהפעלת ה .PC תוספות בעקבות שאלות שנשאלתי: תהליכי CONSלא יודעים כמה הודעות הם צריכים לצרוך (וזה גם יכול להתחלק ביניהם בצורה לא שווה!! צריך מנגנון סנכרון שיאפשר לתהליכי CONSלהסתיים כשכל ההודעות נצרכו .עדיף לא להשתמש ב KILL למטרה הזאת. כל ההודעות צריכות להיות מודפסות בשלמותן! זה חלק מהסנכרון הדרוש (הדפסת הודעה מדמה גישה למשאב משותף). לצורך התרגיל עליכם לייצר קובץ שנקרא pc.cולעדכן את ה MAKEFILEבהתאם .הקובץ הזה יעשה INCLUDE כזה( :קצת לא יפה ..אבל זה עובד): "# include "pc_def.c הקובץ הזה כבר כתוב .הוא כולל את הפונקציות שהוזכרו כאן (אין לשנות אותן) .אתם יכולים לשנות בו את הקבועים כרצונכם .הבודק גם הוא יכול לשנות אותם .עליכם להגיש את התכנית כולל הקובץ הזה כמובן. ~~6 תורידו את הקובץ הזה מהקישור הבאhttp://tzvimelamed.com/lab/files/pc_def.c : הערה :בנוסף לתכנית הנ"ל -כמו בתרגיל מספר – #1גם בתרגיל הזה ,עליכם ליצור כניסה ב MAKEFILE לתכנית משתמש בשם ( .testשנמצאת בקובץ .)test.cהבודק ישתמש בקובץ שלו באותו שם ,בכדי לבדוק את התכנית שלכם .כמובן ,שההגשה שלכם צריכה לכלול קובץ בשם test.cשמכיל תכנית משתמש כלשהי( .אפילו ..hello-worldאבל עוברת קומפילציה! בהצלחה!! ~~7
© Copyright 2024