שבוע #5-6-7
פרקMemory Management :
ניהול הזיכרון
קורס מערכות הפעלה ב'
מכללת הדסה /מכללה חרדית
צבי מלמד
Tzvi.Melamed@gmail.com
הרצאות הקורס מבוססות במידה רבה ביותר על ההרצאות של ד"ר יורם ביברמן
© כל הזכויות שמורות לד"ר יורם ביברמן ולצבי מלמד
©צבי מלמד
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
© Copyright 2025