This question spans 4 stages — each part below is tagged with, and links to, the stage it belongs to.
שימי לב להנחיה 5 בתחילת הבחינה. נתון הקוד הבא: 1. int threads_pipe[2]; 2. void* canceller(void* arg) { 3. pthread_t *pthread_ids = (pthread_t*) arg; /* an array */ 4. int rand = random() % 2; 5. pthread_cancel(pthread_ids[rand]); 6. pthread_exit(NULL); 7. printf("goodbye from canceller\n"); 8. return NULL; 9. } 10. void* piper(void* arg){ 11. const char *i = (const char*)arg; /* "0" or "1” */ 12. printf("thread %s\n", i); 13. char buff[1]; 14. read(threads_pipe[0], buff, 1); 15. if(strcmp(i, "0")==0) { printf("Dan\n"); sleep(1); printf("Leonid\n"); } 16. else /* i is "1" */ { printf("234123\n"); } 17. write(threads_pipe[1], buff, 1); 18. pthread_exit(NULL); 19. return NULL; 20. } 21. int main(int argc, char *argv[]) { 22. pipe(threads_pipe); 23. write(threads_pipe[1], argv[0], 1); 24. if((argc > 1) && (strcmp(argv[1], "-r" )== 0)) 25. dup2(open("output.txt", O_CREAT| O_RDWR, 0666), 1); 26. else if((argc > 1) && (strcmp(argv[1], "-c") == 0)) 27. close(1); 28. pthread_t pthread_ids[3]; 29. pthread_create(&pthread_ids[0], NULL, piper , "0"); 30. pthread_create(&pthread_ids[1], NULL, piper , "1"); 31. pthread_create(&pthread_ids[2], NULL, canceller, pthread_ids); 32. for(int i=0; i<3; i++) 33. pthread_join(pthread_ids[i], NULL); 34. return 0; 35. }
Full original question text (raw OCR)
שאלה 4 – IPC (': 28 שימי לב להנחיה 5 בתחילת הבחינה. נתון הקוד הבא: 1 2 3 4 int threads_pipe[2]; void* canceller(void* arg) { pthread_t *pthread_ids = (pthread_t*) arg; /* an array */ int rand = random() % 2; 5 pthread_cancel(pthread_ids[rand]); 6 pthread_exit(NULL); 7 printf("goodbye from canceller\n"); 8 return NULL; 9 } 10 void* piper(void* arg){ 11 const char *i = (const char*)arg; /* "0" or "1” */ 12 printf("thread %s\n", i); 13 char buff[1]; 14 read(threads_pipe[0], buff, 1); 15 if(strcmp(i, "0")==0) { printf("Dan\n"); sleep(1); printf("Leonid\n"); } 16 else /* i is "1" */ { printf("234123\n"); } 17 write(threads_pipe[1], buff, 1); 18 pthread_exit(NULL); 19 return NULL; 20 } 21 int main(int argc, char *argv[]) { 22 pipe(threads_pipe); 23 write(threads_pipe[1], argv[0], 1); 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 } if((argc > 1) && (strcmp(argv[1], "-r" )== 0)) dup2(open("output.txt", O_CREAT| O_RDWR, 0666), 1); else if((argc > 1) && (strcmp(argv[1], "-c") == 0)) close(1); pthread_t pthread_ids[3]; pthread_create(&pthread_ids[0], NULL, piper , "0"); pthread_create(&pthread_ids[1], NULL, piper , "1"); pthread_create(&pthread_ids[2], NULL, canceller, pthread_ids); for(int i=0; i<3; i++) pthread_join(pthread_ids[i], NULL); return 0; 1. (1 נק') המשפט "goodbye from canceller" אף פעם לא יודפס. כן / לא (הקיפי) נימוק: 2. (4 נק') ה-pipes בקוד הנתון משמשים פונקציונלית כמנעולים. כן / לא (הקיפי) נימוק: 3. (5 נק') קיימת ריצה שבה תודפס (בין היתר) המילה "thread" למסך. כן / לא (הקיפי) נימוק: 4. (5 נק') נניח שהקובץ output.txt לא קיים והקריאה ל open (בשורה 27) לא כוללת את O_CREAT, מה יקרה כשנריץ את התוכנית עם הדגל "r-"? הסבר: 5. (5 נק') קיימת ריצה שבה יודפס (בין היתר) הפלט הבא. כן / לא (הקיפי) Dan 234123 Leonid נימוק: 6.(4 נק') בהכרח נקבל קוד יציאה (exit status אפס. כן / לא (הקיפי) נימוק: 7. (4 נק') הציעי הוספה של קריאת מערכת אחת בלבד (ושום דבר אחר) בשורה 25 שתדפיס למסך פלט כלשהו וגם תמנע יצירת חוטים. שורת הקוד שנוסיף: נימוק:
(1 נק') המשפט "goodbye from canceller" אף פעם לא יודפס. כן / לא (הקיפי) נימוק:
libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction(4 נק') ה-pipes בקוד הנתון משמשים פונקציונלית כמנעולים. כן / לא (הקיפי) נימוק:
Pipe IPC semanticsMutex correctness and deadlock avoidance(5 נק') קיימת ריצה שבה תודפס (בין היתר) המילה "thread" למסך. כן / לא (הקיפי) נימוק:
Pipe IPC semantics(5 נק') נניח שהקובץ output.txt לא קיים והקריאה ל open (בשורה 27) לא כוללת את O_CREAT, מה יקרה כשנריץ את התוכנית עם הדגל "r-"? הסבר:
libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction(5 נק') קיימת ריצה שבה יודפס (בין היתר) הפלט הבא. כן / לא (הקיפי) Dan 234123 Leonid נימוק:
libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction(4 נק') בהכרח נקבל קוד יציאה (exit status אפס. כן / לא (הקיפי) נימוק:
libc syscall wrapper caching pitfallsMutex correctness and deadlock avoidanceSRT / preemptive Gantt construction(4 נק') הציעי הוספה של קריאת מערכת אחת בלבד (ושום דבר אחר) בשורה 25 שתדפיס למסך פלט כלשהו וגם תמנע יצירת חוטים. שורת הקוד שנוסיף: נימוק:
libc syscall wrapper caching pitfallsPipe IPC semantics
The exam question — original PDF
Exactly 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.
Shared memory communication – example // Assume that filling g_msg requires a lot of // computational work. // So we want to use 2 threads, one thread to fill the // first half of g_msg, and another to fill the second half void fill_g_msg( void ) { pthread_t t1, t2; // launch the two threads pthread_create(&t1, NULL, thread_fill, “first"); pthread_create(&t2, NULL, thread_fill, “second"); // wait for both threads to finish pthread_join(t1, NULL); pthread_join(t2, NULL); } OS (234123) – threads vs. processes 25
inodes & *stat syscalls • lstat(2) – Exactly the same as stat(2) if applied to a hard link – But if applied to a symlink, would return the information of this symlink (not to the target of the symlink) – In this case, POSIX says that the only fields within the stat structure that you can portably use are: • st_mode which will specify that the file is a symlink • st_size symlink content length (= length of target filepath) – The value of the rest of the fields could be valid, but it is not specified by POSIX – Notably, it is not specified if a symlink has a corresponding inode • Will be discussed shortly OS (234123) - files 34
קריאות המערכת getpid(), getppid()pid_t getpid();קריאת מערכת המחזירה לתהליך הקורא את ה-pid של עצמו.pid_t getppid();קריאת מערכת המחזירה את ה-PID של תהליך האב של התהליך הקורא.שאלה: מה המשמעות של getppid() == 1 עבור תהליך משתמש טיפוסי?תשובה: תהליך האב הוא init. קורה למשל אם תהליך הבן יתום.מערכות הפעלה - תרגול 222
FD (file descriptors)כל פעולות קלט/פלט של תהליך בלינוקס מבוצעות דרך "קבצים":קבצים "רגילים" לאחסון מידע (/usr/file.txt) נמצאים בדיסק.התקני חומרה גם כן מיוצגים כקבצים, אבל נמצאים בזיכרון.למשל, העכברים המחוברים למחשב מיוצגים כ- /dev/input/mouseN .גם ערוצי תקשורת כמו pipes מיוצגים ע"י קבצים שנמצאים בזיכרון.הקשר בין תהליך לבין קובץ שהוא ניגש אליו נשמר, ברמת המשתמש, ע"י מספר שלם שנקרא file descriptor (FD).לדוגמה: קריאת המערכת open() מחזירה FD.המשתמש מעביר את ה-FD לקריאות מערכת כמו read(), write() כדי לקרוא ולכתוב לקובץ.מערכות הפעלה - תרגול 320
שחרור file objectשאלה: מי מבצע את שחרור הזיכרון של file object? מתי ניתן לשחררו? ייתכנו מצבים בהם תהליכים שונים מצביעים לאותו file object, לכן שחרור ה-file object יכול להתבצע רק לאחר ביצוע close() מכל התהליכים החולקים את אותו ה-file object. זכרו של-file object יש מונה (f_count) הסופר את כמות התהליכים המצביעים עליו בכל רגע נתון. המונה קטן באחד עם כל פעולת close() על האובייקט. כאשר המונה מתאפס, ה-file object ישוחרר.מערכות הפעלה - תרגול 342
דוגמת FCFSaverageResponseTime = (10 + 20 + 30) / 3 = 20כעת נסיר את הנחה 1 ("כל התהליכים רצים למשך אותו זמן"). לכל תהליך זמן ריצה משלו.תוכלו לחשוב על דוגמה שבה FCFS אינו יעיל?מערכות הפעלה - תרגול 59כל התהליכים רצים למשך אותו זמן.כל התהליכים מגיעים באותו זמן (t=0).אם תהליך התחיל לרוץ, אז הוא ירוץ עד לסיומו ללא הפסקות.התהליכים משתמשים רק במעבד ולא מבצעים I/O.זמן הריצה של כל התהליכים ידוע מראש.
סכמת עבודהמערכות הפעלה - תרגול 711שימו לב: שילוב בין תהליכים לחוטים הוא אפשרי אך אינו מומלץ.
יצירת חוט חדשפרמטרים:thread – מצביע למקום בו יאוחסן מזהה החוט החדש במקרה של סיום הפונקציה בהצלחה.attr – מאפיינים המתארים את תכונות החוט החדש, כגון האם החוט הוא חוט גרעין או חוט משתמש, האם ניתן לבצע לו join, כלומר להמתין לסיומו, וכו'. בד"כ נספק ערך NULL המציין חוט ברירת המחדל של המערכת, שניתן להמתין לסיומו.void* (*start_routine)(void*) מצביע לפונקציה שתהווה את קוד החוט. הערך המוחזר מפונקציה זו במקרה של סיומה הטבעי הינו ערך הסיום של החוט.arg – פרמטר שיסופק לפונקציה עם הפעלתה.מערכות הפעלה - תרגול 714
המתנה לסיום חוטפרמטרים:thread – מזהה החוט שממתינים לסיומו.לא ניתן להמתין ל"סיום חוט כלשהו" בדומה ל-wait().thread_return – מצביע למקום בו יאוחסן ערך הסיום של החוט עבורו ממתינים.ניתן לציין NULL כדי להתעלם מערך הסיום.ערך מוחזר: 0 במקרה של הצלחה, וערך שונה מ-0 במקרה כישלון. כמו כן, במקרה של הצלחה ערך הסיום נכתב למשתנה המוצבע ע"י thread_return (אם אינו NULL).מערכות הפעלה - תרגול 719
משתנה תנאי (condition variable)משתנה תנאי הוא אובייקט סנכרון המאפשר לחוט לצאת להמתנה בתוך קטע קריטי.כלומר, לפנות את המעבד ולצאת לתור המתנה.ההמתנה תתבצע עד לקיום תנאי כלשהו.ההמתנה מאפשרת לאכוף סדר בביצוע של החוטים. שימוש תכנותי נכון במשתני תנאי מחייב להגדיר גם:משתנה מצב – החוט עובר להמתנה או חוזר מהמתנה בהתאם לערכו של משתנה המצב.מנעול mutex – מבטיח לנו אטומיות והגנה על הקטע הקריטי.מערכות הפעלה - תרגול 86
סכימה כללית למשתני תנאיcond_t c; // should be initializedmutex_t m; // should be initializedint state_var = 0;החוט הממתין לאירוע יקרא ל:while (!condition_holds(state_var)) cond_wait(&c, &m);החוט שמסמן לחוטים הממתינים להמשיך יקרא ל:if (condition_holds(state_var)) cond_signal(&c);מערכות הפעלה - תרגול 87מדוע cond_wait() מקבלתגם את המנעול?
המתנה על משתני תנאיint pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);פעולה: משחררת את המנעול ומעבירה את החוט להמתין על משתנה התנאי באופן אטומי (ראינו קודם מדוע זה הכרחי).החוט הממתין חייב להחזיק במנעול mutex לפני הקריאה.בחזרה מהמתנה על משתנה התנאי, החוט עובר להמתין על המנעול. החוט יחזור מהקריאה ל-pthread_cond_wait() רק לאחר שינעל מחדש את ה-mutex.ערך מוחזר: הפעולה תמיד מצליחה ומחזירה 0.11מערכות הפעלה - תרגול 8
בלינוקס יש שני סוגי קישורים (links)soft / symbolic linkln -s src dstקישור סימבולי הוא קובץ חדש עם inode נפרד מזה של הקובץ המקורי.כתיבה דרך הקישור כותבת לקובץ אליו הוא מצביע.מחיקת הקישור (באמצעות הפקודה rm) לא תמחק את הקובץ המוצבע.אפשר ליצור קישורים סימבוליים גם לקובץ שלא קיים.hard linkln src dstקישור קשיח הוא שם נרדף לקובץ המקורי כי הוא מצביע ישירות ל-inode של הקובץ המקורי.כתיבה דרך הקישור כותבת לקובץ אליו הוא מצביע.מחיקת הקישור תקטין את מונה הקישורים של הקובץ (כפי שנשמר ב-inode).הקובץ יימחק מהדיסק רק כאשר כל ה-hard links אליו יימחקו.מערכות הפעלה - תרגול 1213
>> rm /A/helloמערכות הפעלה - תרגול 1219inode #2type=dirdatanameinode #A5B7inode #5type=dirdatanameinode #…………inode #13type=soft_linkdatainode #7type=dirdatanameinode #soft13……data block/A/helloקישור "שבור"!dangling link
The exam text, the skills it tests, and the exact slides are already in context.