ניהול הזיכרון memory management - ברוכים הבאים לדף הבית של צבי מלמד
Transcription
ניהול הזיכרון memory management - ברוכים הבאים לדף הבית של צבי מלמד
שבוע #5-6-7 פרקMemory Management : ניהול הזיכרון קורס מערכות הפעלה ב' מכללת הדסה /מכללה חרדית צבי מלמד [email protected] הרצאות הקורס מבוססות במידה רבה ביותר על ההרצאות של ד"ר יורם ביברמן © כל הזכויות שמורות לד"ר יורם ביברמן ולצבי מלמד ©צבי מלמד 1 טבלת הדפים והגנות )(protection • הגנה על הזיכרון מושגת בין ,היתר ,באמצעות טבלת הדפים. • בכל כניסה מסומנים מספר ביטים )לצד מספר המסגרת שאליה ממופה הדף(: – הדף לקריאה ,או לכתיבה ,או לביצוע )מכיל קוד( – מותרת פניה לדף במצב משתמש או רק במצב גרעין – האם הדף וולידי )בתוקף( – נכלל במרחב הכתובות של התהליך )בלינוקס יתכנו חורים במרחב הכתובות( – האם הדף בזיכרון או בדיסק ©צבי מלמד 60 מבנה טבלת הדפים • כתובת 32 -סיביות או 64סיביות • נניח – 32סיביות ,וגודל דף 2^12 :בתים .מספר דפים ~מיליון • גודל הטבלה) :בהנחה 4 ,בתים לכל כניסה( 1024 ≈ 4MB :דפים • הקצאת גודל זיכרון כזה ,ושיהיה רציף – אילוץ קשה – מה גם ...שלעתים קרובות חלקים גדולים ממרחב הכתובות כלל אינם בשימוש • השאיפה: – לארגן את הטבלה בדרך אחרת ,חלופית. – נכיר מספר גישות לכך ©צבי מלמד 61 מבנה טבלת הדפים • גישה א': – להפוך את הטבלה לעץ בעל שתיים או יותר רמות – גישה שכיחה ,מקובלת גם בלינוקס – two level paging – 20הביטים של "כתובת הדף" מחולקים לשתי קבוצות של 10ביטים: • – 10 MS-Bitsהכניסה בטבלה החיצונית • הטבלה החיצונית מכילה 2^10כניסות • – 10 LS-Bitsה offset -בתוך הטבלה החיצונית ,משמשת במצביע לטבלה הפנימית. • בטבלה הפנימית :כל כניסה היא בת 10סיביות שמתאימה ל- "10הסיביות הנמוכות" של כתובת הדף • גישה זאת מקובלת במעבדי Pentium • גישה זאת נקראת) forward-mapped page table:תרגום חופשי: "טבלת דפים עם מיפוי קדימה"( ©צבי מלמד 62 טבלת הדפים בעלת 2רמות ©צבי מלמד 63 דוגמא – טבלת מיפוי בשתי רמות מיפוי בשתי רמות מזיכרון סיביות20 ווירטואלי של סיביות16 לזיכרון פיזי של CPU p1 p2 20 PTBR 16 o 10 + Virtual Addresses 1 page table p1 f + p2 First-Level Page Table 64 Physical Addresses ©צבי מלמד Second-Level Page Table Memory f 16 o 10 ”can we use “forward mapped page table ?for 64 bit addressing • השיטה איננה יעילה/סבירה עבור כתובות של 64ביט ...בגלל ריבוי הרמות. • נכיר שיטות אחרות ©צבי מלמד 65 מבנה טבלת הדפים במעבדי / X-86לינוקס • מרחב הכתובות של התהליך בגודל 3GB = 3*230 • גודל דף212 = 4KB : • לכן מרחב הכתובות מכיל 0.75 *220דפים • כל כניסה בטבלה היא בת 4בתים )כתובת = 32סיביות( • טבלת הדפים תשתרע על פני 768דפים )( 0.75 *210 • זה לא מעשי להקצות טבלה רציפה כזאת לכל תהליך. ©צבי מלמד 66 מבנה טבלת הדפים במעבדי / X-86לינוקס • רוב התהליכים לא משתמשים בכל מרחב הכתובות • משתמשים בכתובות שמפוזרות במרחב – – text segmentבכתובות נמוכות – המחסנית – בקצה העליון ,גדלה כלפי מטה ,בעוד שהערמה גדלה לכוון המחסנית – data + BSS segmentוספריות דינאמיות – "במרכז" מרחב הכתובות • הפתרון: – מרחב הכתובות מוחזק כעץ. – תתי עץ שאינם בשימוש – נגזמים )עץ מדולל או גזום( – הטבלה איננה חייבת להיות רציפה – הטבלה אינה צורכת את כל 768הדפים ©צבי מלמד 67 מבנה טבלת הדפים בלינוקס )הרמה הגבוהה ביותר( PGD – Page Global Directory • )הרמה האמצעית( PMD – Page Middle Directory • הרמה הנמוכה(( PTE – Page Table Entry • ©צבי מלמד 68 מבנה טבלת הדפים בלינוקס • PGD – Page Global Directory – 4כניסות ,אחת מהן איננה בשימוש )כל כניסה מכסה (1GB – שתי ספרות עליונות של הכתובת מגדירות את השורה הרצויה בטבלה. – כל כניסה בטבלה מצביעה על הכניסה המתאימה בPMD- • PMD – Page Middle Directory – 512כניסות )כתובת 9 :ביטים( – סיביות 21-29בכתובת מפנות לכניסה המתאימה בטבלה – כל כניסה יכולה להיות NULLאו להצביע על טבלת ) PTEברמה הנמוכה יותר( • PTE – Page Table Entry – 512כניסות – סיביות 12-20 – כל כניסה מצביעה על ה frame-המתאים בזיכרון הפיזי ©צבי מלמד 69 מבנה טבלת הדפים בלינוקס ©צבי מלמד 70 טבלת הדפים בלינוקס -הערות • לעתים ארכיטקטורות טבלת הדפים היא רק בעלת שתי רמות – זה נכון גם ב X86 -ישנות יותר ,כאשר לא היה PAE ) (Physical Address Extensionאו כאשר ה PAE-איננו "מודלק" • במקרה כזה לינוקס מבצע "אמולציה" של שלוש טבלאות: – הטבלה האמצעית ) (PMDהיא "מנוונת" – בעל כניסה אחת בלבד. – טבלת PGDכוללת (1024) 210כניסות ומצביעה לטבלת PTE שגם היא מכילה 210כניסות – PTEמפנה לדף הרצוי )בגודל – 4Kללא שינוי( ©צבי מלמד 71 טבלת הדפים בלינוקס -הערות • לינוקס מספקת APIלמודל של שלוש רמות )שמסתיר את הפרטים או השונות הארכיטקטונית(. • למעשה ,המעבד צריך לספק ללינוקס translation macros שיאפשרו את התרגום של הכתובות באמצעות שלושת הטבלאות • בצורה גסה: .. ;)• pmd = pmd_offset(pgd, address ;)• pte = *pte_offset_map(pmd, address ;)• page = pte_page(pte • הסידור הזה מוצלח דיו עד כדי כך ,שאותו קוד של לינוקס מטפל במעבד אלפא בעל שלוש רמות ובמעבדי פנטיום בעלי שתי רמות. ©צבי מלמד 72 הערות- טבלת הדפים בלינוקס Each platform that Linux runs on must provide translation macros that allow the kernel to traverse the page tables for a particular process. This way, the kernel does not need to know the format of the page table entries or how they are arranged. This is so successful that Linux uses the same page table manipulation code for the Alpha processor, which has three levels of page tables, and for Intel x86 processors, which have two levels of page tables. 73 ©צבי מלמד הערות- טבלת הדפים בלינוקס The only problem is that some hardware actually supports four-level tables. The example which is driving the current changes is x86-64. The current x86-64 port emulates a three-level architecture by using a single, shared, top-level directory ("PML4") and fitting (most of) the virtual address space in a three-level tree pointed to by a single PML4 entry. It all works, but it limits Linux processes to a mere 512GB of virtual address space. Such limits are irksome to the kernel developers when the hardware can do more, and, besides, somebody is likely to release a web browser or office suite which runs into that limit in the near future. The solution is to shift the kernel over to using four-level page tables everywhere, with the fourth level emulated (and optimized out of existence) on architectures which do not support it. Andi Kleen has posted a four-level page tables patch which implements this change. With Andi's patch, the x86-64 architecture implements a 512-entry PML4 directory, 512-entry PGD, 512-entry PMD, and 512-entry PTE. After various deductions, that is sufficient to implement a 128TB address space, which should last for a little while. 74 ©צבי מלמד הקצאת זיכרון נוסף לתהליך • כאשר נידרש להקצות זיכרון נוסף לתהליך ,אזי: א -אם בדפים הקיימים קיים שטח זיכרון רציף מספיק גדול – נשתמש בו ב -אחרת – צריך לאתר כניסה פניה בטבלת הדפים ,ושם להוסיף מצביעים וצמתים נוספים. ©צבי מלמד 75 hashed page table • פתרון חלופי לעץ-טבלאות ) – (multi-level page tableגישת hash • מספר הדף "מוזן" לפונקצית Hashשמפנה אותנו לכניסה כלשהי בטבלה. • כל כניסה בטבלה מכילה רשימה מקושרת של איברים .כל איבר: – מספר דף לוגי )הערך שהכנסנו לפונקצית ה(hash- – מספר המסגרת הפיזית frame – מצביע לאיבר הבא ברשימה • סורקים את הרשימה סדרתית ,ומשווים את מספר הדף הלוגי ברשימה לזה שדרוש – עד שנמצא או עד לסיום )הדף איננו בזיכרון(. ©צבי מלמד 76 hashed page table 77 ©צבי מלמד hashed page table חישובי עלות )זמנים( • נניח ש- – הטבלה מספיק קטנה בכדי להיות מוחזקת ברגיסטרים – on-die ) – (= on chipכלומר על המעבד עצמו – איברי הרשימות המקושרות נמצאות בזיכרון • אזי ,משך הזמן לכתובת רצויה = אורך הרשימה שיש לסרוק + גישה ל frame-הדרוש • בטבלת גיבוב – השאיפה שההתנגשויות תהיינה מועטות ,כלומר על פי רוב רשימה באורך אחד. ©צבי מלמד 78 inverted page table טבלת דפים מהופכת • מוטיבציה :טבלאות הדפים משוכפלות עבור כל תהליך – דבר שמבזבז הרבה זיכרון • הפתרון :נחזיק "טבלת דפים מהופכת" לכל התהליכים. – כניסה/שורה אחת לכל ) frameכלומר לכל דף פיזי( – בכניסה נשמור :מספר התהליך +מספר הדף בתהליך שעבורו הוקצה הדף הפיזי – לדוגמא :בתהליך 3879דף )לוגי( מספר #40הוקצה ל frame-מספר .#57אזי ,שורה מספר #57בטבלה תכיל את הערכים(3879, 40): – כאשר תהליך 3879מבקש כתובת לוגית בהיסט כלשהו ,בדף ,40 צריך לסרוק את הטבלה עד שנמצאת השורה )מספר (57שמכילה את הערכים )(3879, 40 ©צבי מלמד 79 inverted page table טבלת דפים מהופכת ©צבי מלמד 80 inverted page table טבלת דפים מהופכת • הפתרון הזה אומץ במעבדי ) UltraSparc (SunובPowerPC - )(IBM, Motorola, Apple • בעיה :צריך לסרוק טבלה מאוד גדולה בכדי לקבל תשובה • פתרון :שילוב עם hashing – hashingמתבצע על הזוג )(pid, page# ©צבי מלמד 81 דפים משותפים – shared pages • אחת המוטיבציות )או רווחים( לעבודה עם דפים – היכולת לשתף קוד בין תהליכים – כי נפטרנו מהדרישה שהתוכנית תהייה רציפה בזיכרון – פונקציות שנרצה לשתף – רוב ספריות C • ’ – ‘reentrant code’ or ‘pure codeקוד )פונקציה( שניתן לשתף אותו בין תהליכים. • שאלות: – האם כל קוד )פונקציה( היא ?reentrant – אם לא – מתי קוד יהיה ?reentrant – מהן הדרישות המיוחדות מקוד כזה? • צריך לקיים ©צבי מלמד 82 דפים משותפים – shared pages • ’) – ‘reentrant code’ or ‘pure codeקוד )פונקציה( שניתן לשתף אותו בין תהליכים( -צריך לקיים מספר דרישות: .1הקוד אינו משנה את עצמו במהלך הריצה )”(not “self modifying code .2אינו פונה למשתנים גלובליים ,אינו מכיל משתנים סטטיים .3אינו משנה את המערכת הגלובלית – למשל ,שימוש בסמפור .4הקריאות הן רק לפונקציות שהן בעצמן pure-code ©צבי מלמד 83 דפים משותפים – shared pages • טבלאות הדפים של כל תהליך צריכות להצביע למסגרות )דפים פיזיים( של הדפים המשותפים שבהם התהליך משתמש. • כפי שציינו – שימוש בטבלת דפים מהופכת אינו מאפשר לבצע שיתוף של דפים – כי כל מסגרת מכילה pidאחד )ורק אחד(... ©צבי מלמד 84 סגמנטציה – Segmentation • בשיטת הדפים – מחלקים את התוכנית ל'חתיכות' קטנות • החלוקה שרירותית ואינה מתאימה את עצמה לגודל התוכנית • שיטת הסגמנטים: – התוכנית מחולקת למספר )יחסית קטן( של מרכיבים לוגיים – כל סגמנט – בעל משמעות ,מטרה. – גודלם :אינו קבוע ,אלא משתנה בהתאם לצורך. – הקומפיילר יוצר את הסגמנטים השונים הבאים: • קוד התוכנית • משתנים גלובליים • הערימה )להקצאת זיכרון דינמית( • המחסנית )לכל פתיל( • סגמנט לקוד Cמשותף )(C-library ©צבי מלמד 85 סגמנטציה – Segmentation • הקומפיילר מייצר את הסגמנטים השונים. • ה loader-מציב לסגמנטים מספרים )מספר לכל סגמנט( • מרחב הכתובות הלוגי בנוי מ -שם-סגמנט ) offset +בתוך הסגמנט( • לכל סגמנט מוגדר הבסיס שלו והגבול – מאפשר בדיקת חריגות: – לדוגמא ניסיון לבצע קוד בסגמנט של נתונים ,או גישה לנתונים בסגמנט של קוד וכו' ©צבי מלמד 86 סגמנטציה – Segmentation תמיכת החומרה • כתובת לוגית :מס' סגמנט offset + )הסטה( • מספר-סגמנט – הפניה לטבלת הסגמנטים • כניסה בטבלת הסגמנטים: – כתובת בסיס base – אורכו של הסגמנט limit • נבדקת ההסטה offsetלעומת ה- .limitחריגה trap ©צבי מלמד 87 סגמנטציה – Segmentation • • • • הגנה :הסגמנט יחידה לוגית ,ולכן ניתן להגן על כל תכולתו בשלמות )למשל הרשאות .(read/write שיתוף :ע"י הכללת הסגמנט בטבלת הסגמנטים של התהליכים בעיות בשיטת הסגמנטים: – שטח זיכרון רציף ,אורך לא-אחיד – דומה לבעיות הקצאת הזיכרון לפני השימוש בדפים – בעיות הקצאה כגון best-fit, worst-fit – בעיות קיטוע חיצוני הבעיה פחות חמורה: – סגמנט יחידה קטנה יותר מתוכנית שלמה ,אך עדיין... – מבנה הכתובת – בסיס )שמור בטבלה( offset +מאפשר relocation • מה עשוי להיות הפתרון לבעיות הנ"ל? ©צבי מלמד 88 Segmentation with Paging • • • • שילוב פתרונות :סגמנטים +דפים התוכנית מחולקת לסגמנטים – נהנים מיתרונות הסגמנטים כל סגמנט מחולק לדפים – יתרונות הדפים :העדר קיטוע חיצוני ,וויתור על דרישת הרציפות ,יכולת לשמור בדיסק ,מידול זיכרון ווירטואלי גדול באמצעות זיכרון פיזי קטן ,וכו' במעבדי :x86חייבים לעבוד עם סגמנטים .אבל ,העבודה עם דפים היא אופציונלית. – כאמור יתרונות לשילוב של שניהם – אבל מצריך מערכת- הפעלה שיודעת לתמוך בזה ©צבי מלמד 89 Segmentation with Paging הדגמה על מעבדי X86 • תהליך יצירת הכתובת ,מורכב מהשלבים הבאים: – המעבד יוצר כתובת לוגית )מספר הסגמנט (offset + – ה ‘segmentation-unit’ -ממירה אותה לכתובת ליניארית )כתובת "רגילה" במרחב הכתובות הווירטואלי( – ה 'paging-unit’ -ממירה אותה לכתובת פיזית ©צבי מלמד 90 - Segmentationמבנה כתובת לוגית במעבדי X86 • כתובת לוגית -מיוצרת על ידי המעבד • מכילה שני חלקים 16) segment-selector :ביט( ו 32) offset -ביט(. selector הרשאות - הגנות ©צבי מלמד גלובלית או מקומית אינדקס בטבלת הסגמנטים 91 - Segmentationמבנה כתובת לוגית במעבדי X86 selector בהינתן כתובת לוגית: • על פי gפונים לטבלה המתאימה • על פי sפונים לכניסה המתאימה בטבלה הזאת • נשלפת מהטבלה כתובת הבסיס של הסגמנט וכן הlimit- • ה offset-נבדק כנגד ה limit-לוודא שאין חריגה • כתובת הבסיס מתווספת לoffset- ונוצרת הכתובת הליניארית • עם הכתובת הלינארית פונים לטבלת הדפים ,כפי שראינו קודם ©צבי מלמד 92 Segmentation with Paging • דוגמא :מערכת ) OS2של (IBMעל מעבדי X86 – 8092סגמנטים מהם לוקליים לכל תהליך ,והמידע אודותם מוחזק ב(Local Descriptor Table) LDT- – 8092גלובליים – משותפים לכל התהליכים ,ומידע עבורם מוחזק ב (Global Descriptor Table) GDT ©צבי מלמד 93 תרגום מכתובת לוגית לכתובת ליניארית מתוך )Pentiium-Pro developer manual (Intel .1על פי ה index-בsegment - selectorאותרה הכניסה המתאימה בטבלה ) GDT – (or LDTכלומר התקבל הsegment-descriptor - .2נבדקות הרשאות גישה ונבדק שה) offset-ביטים (0-31הוא בתחום החוקי .3כתובת הבסיס של הסגמנט מתווספת לoffset- ומתקבלת הכתובת הליניארית ©צבי מלמד 94 הערות נוספות על סגמנטים • במעבדי פנטיום קיימים 6רגיסטרים ייעודיים לסגמנטים – CS (Code Segment) .1ייעודי למיעון קוד )(code addressing – SS (Stack Segment) .2למיעון מחסנית )(stack addressing .3 ) - DS (Data Segmentלמיעון של Data • בנוסף 3רגיסטרים נוספים ל data -שנקראים ES, FS, GS • כל רגיסטר כזה מכיל: א -segment selector -המידע הנראה visible data ב – segment descriptor -המידע הנסתר • פקודת מכונה שטוענת את ה segment selector-לרגיסטר המתאים – המעבד ידאג לטעון את התוכן המתאים. ©צבי מלמד 95 הערות נוספות על סגמנטים • • • פקודת מכונה שטוענת את ה segment selector-לרגיסטר המתאים – המעבד ידאג לטעון את התוכן המתאים. מהר הרווחנו? – caching – אם אנו עוסקים בסגמנט שנמצא באחד הרגיסטרים – נחסכת פניה לזיכרון הראשי. במחשב עם מספר מעבדים – אחריות התוכנה לדאוג לסינכרון – )יכול להיות שזה השתנה בגרסאות חדשות יותר עם ריבוי ליבות (multi core ©צבי מלמד 96 הערות נוספות על דפים • במעבדי פנטיום דפים יכולים להיות בגודל (4KB) 212או בגודל • .(4MB) 222במקרה כזה טבלת הדפים תהייה ברמה אחת ותכלול 1024כניסות ) 10ביט( • הדפים יכולים להיות משוחלפים לדיסק .במקרה כזה ,יהיה ביט שמציין את זה ,והכתובת ) 32ביט( תהיה הכתובת בדיסק ©צבי מלמד 97