1 / 39

Operating Systems, 142

Operating Systems, 142. Practical Session 11 File Systems & Midterm 2014. Quick recap. Files are an abstraction mechanism Several file types: User files (regular),Directory files, Special files (Block, Char) Access: sequentially (e.g. tapes) or random access (disk)

tara-nelson
Download Presentation

Operating Systems, 142

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Operating Systems, 142 Practical Session 11 File Systems & Midterm 2014

  2. Quick recap • Files are an abstraction mechanism • Several file types: User files (regular),Directory files, Special files (Block, Char) • Access: sequentially (e.g. tapes) or random access (disk) • Data: structured (records) or unstructured (set of bits and bytes)

  3. File system layout (Tanenbaum)

  4. Quick recap: Index-Nodes (i-nodes) • The superblock object represents the entire file system. • Each i-node is a data structure containing pointers to the disk blocks that contain the actual file contents. • An i-node corresponds to a single file. • An i-node needs to be in the main memory only if the correspondent file is open. • Besides the data blocks pointers, the i-node also contains information on the file permissions, owner, etc

  5. Quick recap: i-Nodes General file attributes File Size HardLink count The number of hard-links to the file Usually between 10 and 12

  6. Question 1: i-nodes How many time will the disk be accessed when a user executes the following command: more /usr/tmp/a.txt Assume that: • The size of 'a.txt' is 1 block. • The i-node of the root directory is not in the memory. • Entries 'usr', 'tmp' and 'a.txt' are all located in the first block of their directories.

  7. Question 1: i-nodes Accessing each directory requires at least 2 disk accesses: reading the i-node and the first block. In our case the entry we are looking for is always in the first block so we need exactly 2 disk accesses. According to assumption 2 the root directory's  i-node is located on the disk so we need 6 disk accesses (3 directories) until we reach a.txt'si-node index. Since "more" displays the file's content, for a.txt we need its i-node + all the blocks of the file (1 block, according to assumption). Total disk accesses: 6 + 2 = 8.

  8. Question 1: i-nodes A similar problem

  9. Question 2: i-nodes The Ofer2000 Operating Systems, based on UNIX, provides the following system call: rename(char *old, char *new) This call changes a file’s name from ‘old’ to ‘new’. What is the difference between using this call, and just copying‘old’ to a new file, ‘new’, followed by deleting‘old’? Answer in terms of disk access and allocation.

  10. Question 2: i-nodes • rename- simply changes the file name in the entry of  its directory. • copy -  will allocate a new i-node and the blocks for the new file, and copy the contents of the old file blocks to the new ones. • delete - will release the i-node and blocks of the old file. • copy + delete - is a much more complicated operation for the Operating System, note that you will not be able to execute it if you do not have enough free blocks or i-nodes left on your disk.

  11. Question 3: i-nodes Write an implementation (pseudo code) of the system call: delete(i-node node) Which deletes the file associated with node. Assume that: • nodeis associated with a regular file, and that delete is not recursive. • The i-node has 10 direct block entries, 1 single indirect entry and 1 double indirect entry. • You may use the system calls: read_block(block b) which reads block b from the disk. free_block(block b) andfree_i-node(i-node node).

  12. Question 3: i-nodes delete(i-node node){ // remove the direct blocks for each block b in node.direct do free_block(b); // remove the single indirect blocks single <-- read_block(node.single_indirect) for each entry e in single do free_block(e); free_block(single); // remove the double indirect blocks double <-- read_block(node.double_indirect) for each entry e in double do single <-- read_block(e) for each entry ee in single do free_block(ee); free_block(single); free_block(double); // remove the i-node free_i-node(node); }

  13. Question 4: i-nodes What would be the maximal size of a file in a UNIX system with an address size of 32 bits if : • The block size is 1K • The block size is 4K (The i-node has 10 direct block entries, one single, double & triple indirect)

  14. Question 4: i-nodes • Block size: 1K • Direct: 10·1K • Single indirect: each address is 32 bit = 4 byte then we have 256 pointers to blocks of size 1K (i.e. 256·1K) • The same idea is applied for double and triple indirect. In total: 10·1K+256·1K+256·256·1K+256·256·256·1K

  15. Question 4: i-nodes • Block size: 4K • Direct: 10·4K • Single indirect: each address is 32 bit = 4 byte then we have 1024 pointers to blocks of size 4K (i.e. 1024·4K) • The same idea is applied for double and triple indirect In total: 10·4K+1024·4K+1024·1024·4K+1024·1024·1024·4K

  16. Question 5: i-nodes Assuming that the size of each block is 1K and the address size is 32 bits (4 bytes). Convert byte address (offset) 1,515,000 in our file to the physical address.

  17. Question 5: I-Nodes Byte number 1,515,000 is calculated as follows: • 1st byte of the double indirect block is 10k+256k = 272,384 • byte number 1,515,000 is number 1,242,616 in the double indirect block • every single indirect block has 256k bytes --> byte 1,242,616 is in the 5th single indirect block (4*256k = 1,048,576) • Every entry is 1k, so byte 194,040 is in the 189th block – assume that it points to block 123 on the disk • within block 123 , it is byte #504

  18. Estimation They could say "the connection is probably lost," but it's more fun to do naive time-averaging to give you hope that if you wait around for 1,163 hours, it will finally finish.

  19. Operating SystemsMIDTERM 2014

  20. Question 1 (35 נקודות) מניעה הדדית (mutual exclusion)

  21. Question 1 • נתון אלגוריתם למניעה הדדית (mutual exclusion) לשני תהליכים המשתמש בשני ביטים. כל תהליך כותב וקורא את שני הביטים. שני הביטים מאותחלים לערך 0. התהליכים מסומנים 0 או 1 והקוד המופיע למטה כתוב עבור תהליך i שמקבל את הערך 0 או 1 לפי התהליך המריץ את הקוד. 1 start: x := i; 2 if y ≠ 0 then 3 await y = 0; 4 gotostart; 5 y := 1; 6 if x ≠ ithen 7 y := 0; 8 await x = 0; 9 gotostart; Critical Section y := 0; x := 0; א. האם האלגוריתם מקיים מניעה הדדית? הוכיחו או הפריכו בלא יותר מ-10 שורות (15 נק'). ב. האם האלגוריתם מונע deadlock ? הוכיחו או הפריכו בלא יותר מ-10 שורות (10 נק'). ג. האם תתכן הרעבה ? (10 נק')

  22. Question 1 א. האם האלגוריתם מקיים מניעה הדדית? הוכיחו או הפריכו בלא יותר מ-10 שורות (15 נק'). פתרון: האלגוריתם אינו מקיים מניעה הדדית: נניח שתהליך 1 עובר את שורה 1 ראשון ואחריו תהליך 0. התוצאה היא ש- x = 0. שני התהליכים עוברים לסירוגין את שורות 2-4, כיוון ש- y עדיין שווה 0. כעת תהליך 0 עובר ראשון את שורה 5 ונכנס לקטע הקוד הקריטי. תהליך 1 (שערך x אינו מתאים לו) נכנס לשורות 7-9, חוזר לשורה הראשונה, מבצע את כל הקוד (כיוון ש- y = 0) ואז נכנס גם הוא.

  23. Question 1 ב. האם האלגוריתם מונע deadlock ? הוכיחו או הפריכו בלא יותר מ-10 שורות (10 נק'). פתרון: האלגוריתם אינו מקיים deadlock-freedom. : deadlock עשוי לקרות בתסריט שבו תהליך 0 מבצע מספר לא חסום של פעמים את שורות 1-4 ותהליך 1 מבצע מספר לא חסום של פעמים את שורות 1-9. כל שנדרש הוא: א. שתהליך 1 יעבור את שורה 5 לפני שתהליך 0 מבצע את שורה 2. ב. שתהליך 0 יבצע את שורה 1 לפני שתהליך 1 מבצע את שורה 6. בתאורדינאמי, תהליך 0 מאפשר לתהליך 1 לחזור להתחלה (כי הוא מאפס את x) ואילו תהליך 1 מאפס את y רק אחרי שתהליך 0 עבר את שורה 2. במלים אחרות תהליך 0 אף פעם לא יגיע לשורות 5-9.

  24. Question 1 ג. האם תתכן הרעבה ? (10 נק') פתרון: תתכן הרעבה. נובע ישירות מכך שהאלגוריתם אינו מקיים חופש מקיפאון.

  25. Question 2 (40נקודות) XV6

  26. Question 2 (40 נק') מערכת התרגילים המעשיים – XV6 לפניכם קוד מתוך spinlock.c: 1469// Acquire the lock. 1470// 1471// 1472// 1473void 1474 acquire(struct spinlock *lk) 1475{ 1476pushcli(); 1477if(holding(lk)) 1478 panic("acquire"); 1479 1480// The xchg is atomic. 1481// It also serializes, so that reads after acquire are 1482// not reordered before it. 1483while(xchg(&lk->locked,1)!=0) 1484; 1485 1486// Record info about lock acquisition for debugging. 1487lk->cpu=cpu; 1488getcallerpcs(&lk,lk->pcs); 1489}

  27. Question 2 א. הסבירו ב- 2-3 שורות את מטרת הקוד. הדגימו מקרים של בעיות סנכרון שדורשות את השורות 1476 ו- 1483. בדוגמאות הסבירו מדוע יש צורך לבצע את השורות האלה. (10 נק') פתרון: ה- spinlockנועד לצורך הגנה של מבנים משותפים ע"מ להשיג ME בצורה בטוחה. כדי להבין יותר טוב את המימוש של ה- spinlock נבחין בין 2 מקרים בהם יכולה להתבצע הפרה של ME: • ריצת קוד על ליבה\מעבד שונה מזה אשר ביצע נעילה – כדי לפתור בעיה זו קיים שימוש בפעולה אטומית xchg (שורה 1483). • מעבר לקוד אחר על אותו המעבד (מעבר אסינכרוני בעזרת interrupt – לדוגמא I/O interrupt). בעיה אפשרית הנובעת מכך היא ביצוע acquire על אותו המנעול ע"י אותו המעבד (אפשר כמובן לתת דוגמאות אחרות). כדי למנוע מצב כזה קיים שימוש בביטול interrupts (שורה 1476(.

  28. Question 2 ב. ע"מ לשפר את ביצועי מערכת ההפעלה היינו מעוניינים כי ה- kernel יהיה יעיל ככל הניתן. מאחר ו- spinlock נועד לצרכי kernel בלבד, האם ניתן לשפר את ביצועי ה- spinlock במקרים הבאים: • במערכת בה ה- kernel רץ על מעבד יחיד (עם ליבה יחידה) • במערכת בה ה- kernel משתמש ב- non preemptive scheduler. עבור כל אחד מהמקרים הציעו שיפורים (הורדה / שינוי של הקוד) במידה ושיפור אפשרי, במידה ולא, הסבירו מדוע. נמקו את תשובתכם ב- 2-3 שורות (7 נק').

  29. Question 2 פתרון: בהתאם למקרים אשר נותחו בסעיף הקודם: • כאשר ה- kernel רץ על מחשב עם ליבה (מעבד) יחיד, ניתן לבטל את שורות 1483 ו 1519. אפשר כמובן לבטל את השורות הקשורות למעבד (1487, 1508) ולתקן את holding בהתאם. • לא ניתן לבצע שינויים במערכת הזו מכיוון שקיימים interrupts אשר לא קשורים לתזמון התהליכים.

  30. Question 2 ג. במערכת הפעלה התומכת ב- signals, לאחר ביצוע exec כל ה- handlers חוזרים להיות ה- default handlers. הסבירו מדוע (8 נק'). פתרון: במהלך ביצוע exec system call כל הזיכרון של התהליך מתחלף, בפרט גם ה code segment. אם ה signal handlers לא יוחזרו להיות ברירת מחדל (שינויים של מצביעי הפונקציות) אזי המצביעים הישנים יכולים להצביע על מקומות בזיכרון אשר לא שייכים לתהליך או לא מכילים קוד (במילים אחרות לא יצביעו ל signal handlers הישנים).

  31. Question 2 ד. תארו בשתי שורות בעיה במימוש של default signal handlers . בשתי שורות נוספות תארו כיצד התגברתם על הבעיה במימוש שלכם בעבודה (8 נק'). פתרון: הבעיה היא ש- signal handler הוא קוד משתמש ולא ידוע ב kernel מה כתובת ההתחלה שלו (מצביע לפונקציה). פתרון אפשרי במימוש העבודה השנייה הוא הגדרה של entry point חדש (על ידי שינוי ההגדרות של ה- linker) לתוכנית אשר "עוטף" את ה- main ומבצע רישום של signal handlers. • התקבלו גם תשובות שדנו בבעיה בין user space ל- kernel space והסבירו פתרון אפשרי (קריאה ל- default ישירות מתוך ה- kernel וקריאה ל- non default באמצעות יצירת frame על מחסנית של ה- user).

  32. Question 2 ה. מימוש הסיגנלים שהוגדר בעבודה 2 הניח signal handler אשר לא מקבל ארגומנטים. סטודנט חרוץ ניסה לקרב את המימוש של הסיגנלים ב- xv6 למימוש ב- linuxעל ידי שינוי החתימה של ה- signal handler. במימוש שלו ה- handler קיבל ארגומנט יחיד המייצג את מספר הסיגנל. הסבירו בפירוט אלו שינויים במנגנון הפעלת ה- signal handler הסטודנט ביצע כדי שהמנגנון יעבוד (7 נק').

  33. Question 2 פתרון: • העברת הארגומנט ל- signal handler- הכנסתו למחסנית ה- user. • החלק הבעיתי בהעברת ארגומנט ל- signal handler הוא במציאת דרך לגרום לכך שהארגומנט "ייצא" מהמחסנית (לפי הקונבנציה, מי שמבצע קריאה לפונקציה אחראי על כך). כלומר בזמן הכנת ה- frame להרצת handlerצריכים להכניס בתור כתובת חזרה כתובת פונקציה אשר תדע לבצע ניקוי ארגומנט (בנוסף לארגומנט עצמו). • הפונקציה יכולה להיות גם ב- kernel. נגרום לחזרה ל- kernel בסיום ריצת ה- handlerונבצע את ניקוי הארגומנט מה- kernel.

  34. Question 3 (25 נקודות) system calls

  35. Question 3 1. #include <stdio.h> 2. #include <pthread.h> 3. #include <unistd.h> 4. #include <sys/types.h> 5. #include <signal.h> 6.voidthread_action(){ 7. sleep(10); 8.pid_tpid=getpid(); 9.pthread_ttid=pthread_self(); 10. kill(pid, SIGINT); 11. printf("Pid = %u, Tid = %u\n",(uint)pid,(uint)tid); 12.} 13.voidsigint_handler(){ 14.printf("Received SIGINT\n"); 15.} 16.int main(){ 17. signal(SIGINT,sigint_handler); 18.pthread_t thread1, thread2; 19.pthread_create(&thread1,NULL,(void*)&thread_action,NULL); 20. fork(); 21.pthread_create(&thread1,NULL,(void*)&thread_action,NULL); 22.pid_tpid=getpid(); 23.printf("Pid = %d Finished run!\n",pid); 24.pthread_exit(NULL); 25.} נתונה התוכנית הבאה :

  36. Question 3 א. (15 נק'). ציין את הפלטים האפשריים של התוכנית והסבר במדויק ובקצרה מדוע אלו הפלטים העשויים לנבוע מריצת התכנית. (ניתן להניח ש10 שניות שינה הן זמן מספיק עבור ה-thread הראשי לבצע את כל הפקודות בmain).

  37. Question 3 • פתרון: • נרשמת הפונ' signal_handler עבור הסיגנל SIGINT • נוצר thread ראשון t1 עבור התהליך (נסמנוp1) • נוצר תהליך חדש נסמנוp2 (הthread t1 של p1 אינו קיים בp2 הנוכחי מכיוון שfork אינו משכפל threadים בposix) • נוצר thread חדש t2 עבור p1 וthread חדש t1 עבור p2 • כל הthreadים נכנסים למצב sleep (הסדר לא משנה) • p1וp2 מדפיסים את ההודעה שלהם • כעת עבור p2 יודפס בהכרח received sigint ולאחר מכן “pid = 2, tid = 1” • עבור p1 • או שלא יודפס כלום • או שיודפס recivedsigint ולאחריו “pid = 1,tid = 1 | 2” • או רק received sigint • או שיודפס recivedsigint ולאחר מכן 2 ההדפסות בלי יציאת התוכנית • הדבר תלוי בתזמון של הthreadים מכיוון שרישום הפונ ע"י signal הינו חד פעמי אך אם 2 הסיגנלים התקבלו באותו הזמן (לפני חזרה של אחר מהthreadים למצב משתמש) רק אחד מהthreadים יאסוף את הסיגנל מכיוון שסיגנלים אינם מצטברים. • הסדר בין הטיפול בp1 וp2 אינו מובטח

  38. Question 3 ב. (5 נק') האם הסיגנל שנשלח בשורה 10 הינו סינכרוני או א-סינכרוני? תן דוגמא לקריאה לסיגנל מהסוג השני. (כלומר, אם ענית שהסיגנל הוא א-סינכרוני תן דוגמא לסיגנל סינכרוני, ולהיפך). פתרון: • הטיפול הינו סנכרוני מכיוון שהקריאה לkill הינה קריאת מערכת אפשר מעבירה אותנו למצב kernel ובו מסומן על התהליך שקרא שהתקבל סיגנל, כשתסתיים הקריאה ונרצה לחזור למצב משתמש נראה שישנו סיגנל ונחזור ישר לטיפול בו. • דוגמא לטיפול לא סינכרוני הוא שימוש בkill על מנת לשלוח סיגנל לתהליך אחר.

  39. Question 3 ג. (5 נק') איך ישתנה הפלט אם נוריד את השורה האחרונה: pthread_exit(NULL)? פתרון:אם נוריד את pthread_exit הthread הראשי יסיים את הפונ' main מה שיגרום לקריאה בלתי מפורשת לפונקציה exit() והתהליך יסגר מבלי לאפשר לחוטים להדפיס את ההודעות שלהם או לשלוח סיגנל.

More Related