פונקציות הקשורות לניהול זיכרון
שמורה המנוהלת על ידי הפונקציות לטיפול בזיכרון: בלוקים ברשימת הזיכרון הפנוי ממוינים בסדר עולה לפי כתובתם.
המערכת אינה יכולה להבטיח שזיכרון שהוקצה לתהליך בעזרת getmem ישתחרר כשתהליך מסתיים, וזאת מכיוון שהיא איננה שומרת איזה זיכרון שייך לכל תהליך. לכן: תהליך חייב לשחרר את כל הזיכרון שהוא הקצה מהערימה לפני שהוא מסתיים. הפונקציה משתמשת במקרו roundew(), המקבל מספר ומחזיר את העיגול שלו כלפי מעלה למספר הבא המתחלק ב-4. המקרו מוסיף 3 למספר, ואז מחזיר ממנו את שארית החלוקה שלו ב-4. מכיוון שהרשימה המקושרת היא רשימה חד כיוונית, דרושים שני מצביעים כדי לסרוק ולמצוא את הבלקו המבוקש. כאשר נמצא בלוק בגודש המבוקש: אם הבלוק בדיוק בגודל הרצוי, getmem מוחקת את הבלוק מרשימת הבלוקים הפנויים ומחזירה את כתובתו. אחרת, הפונקציה מחזירה בלוק בגודל nbytes מתחילת הבלוק הפנוי שמצאנו, ומשרשרת את שאר הבלוק הפנוי בחזרה אל רשימת הפנויים. כאשר אנו מפצלים בלוק בצורה זו, המשתנה הפנימי leftover מצביע אל תחילת הקטע אותו נרצה לשרשר. החישוב כדי למצוא את leftover הוא פשוט: leftover נמצא במרחק nbytes בתים מתחילת הבלוק. נשים לב שהוספת nbytes ל-p לא תשיג את התוצאה הרצויה, עקב אריתמטיקת המצביעים של שפת C. לכן, כדי לבצע חישוב מספרי, ראשית אנו ממירים את p ל-(char*), ולאחר מכין אנו ממירים את p בחזרה ל-(struct mblock*). בפונקציה יש באג: הפונקציה בודקת אם כמות הזיכרון המבוקשת שווה ל-0, ואז מחזירה שגיאה, אבל היא אינה בודקת מקרה בו כמות הזיכרון המבוקשת קטנה מ-0.
בדומה ל-getmem, שני המצביעים p, q רצים על רשימת הזיכרון הפנוי. אנחנו עוצרים כאשר כתובת הזיכרון אותו רוצים לשחרר נמצאת ביניהם. פונקציה זו מורכבת יותר מ-getmem, מכיוון שכאשר נשחרר זיכרון, אם ייווצרו מספר בלוקים ריקים ברצף נרצה לאחד אותם לבלוק גדול אחד. q מצביע אל הבלוק הפנוי שלפני הבלוק שרוצים לשחרר. p מצביע אל הבלוק הפנוי שאחרי הבלוק שרוצים לשחרר. אם q הוא NULL, אין בלוק פנוי לפני. אם p הוא NULL, אין בלוק פנוי אחרי. בפונקציה יש באג: הפונקציה בודקת אם כמות הזיכרון המבוקשת שווה ל-0, ואז מחזירה שגיאה, אבל היא אינה בודקת מקרה בו כמות הזיכרון המבוקשת קטנה מ-0. בפונקציה זו יש גם באג נוסף: הפונקציה איננה משרשרת את הזיכרון הפנוי כראוי. נביט כעת בקוד הפונקציה, וננתח מה היא צריכה לעשות ומה היא עושה, על מנת לזהות את הבאג. ננתח כעת את הפונקציה.
בשורה (1) אנו בודקים שלא גלשנו מגבולות הזיכרון הפנוי להקצאה – מלמעלה ומלמטה.
שורה (2): שני המצביעים q, p מטיילים על הרשימה. בסוף הלולאה: q מצביע אל הבלוק הפנוי שלפני הבלוק שרוצים לשחרר. p מצביע אל הבלוק הפנוי שאחרי הבלוק שרוצים לשחרר.
לאחר שקבענו את ערכי q, p, נבדוק שחוקי לשחרר את הבלוק המבוקש. ישנם שני מצבים בהם לא חוקי לשחרר את הבלוק:
שורה (3) מטפלת באפשרות מספר 1. שורה (4) מטפלת באפשרות מספר 2.
מצב זה מטופל בשורה (6): - שמים בתחילת block את הרשומה החדשה. - memlist מצביע כעת על block.
טיפול ראשון למצב זה בשורה (6): - שמים בתחילת block את הרשומה החדשה. - memlist מצביע כעת על block. כעת נבדוק האם צריך לאחד את הבלוק הפנוי החדש עם הבלוק הפנוי שאחריו או שלא. אם לא צריך לאחד את הבלוקים, סיימנו. אחרת, שורה (7) דואגת לאיחוד.
טיפול ראשון בשורה (5): מרחיבים את q לכלול גם את block. טיפול שני בשורה (7): מרחיבים את q לכלול גם את p, ומוציאים את p מהרשימה.
שורה (5) מטפלת במקרה זה. q גדל כדי לכלול את block.
במקרה זה אנו רואים את הבאג שבפונקציה freemem: שורה (6) גורמת ש-block יהיה הבלוק הראשון ברשימה. כל הזיכרון הפנוי שהיה לפני block נאבד.
גם מקרה זה לא מטופל כראוי על ידי freemem. גם במקרה זה, הזיכרון שלפני block נאבד. תגיות המסמך: |
תוכן העניינים:
שיתוף: |
תודה
הסברתם את זה, כמו שאר הנושאים, באופן הכי ברור שיש.