بسم الله الرحمن الرحيم.
بعد أن تحدثنا عن الجدولة في الدرس السابق، سننتقل اليوم إلى أحد أعمدة أنظمة التشغيل: إدارة الذاكرة الرئيسية. وقد سبق أن لمسنا جانباً عملياً منها في درس الذاكرة الافتراضية ضمن ورشة لغة C؛ وهذا الدرس هو الأساس النظري الذي يقف عليه ذلك كله.
الخلفية (Background)
نظام التشغيل الحديث يجب أن يتيح لأعداد كبيرة من العمليات أن تكون في الذاكرة في وقت واحد للتنفيذ المتزامن، وهذا ما يجعل مهمة إدارة الذاكرة معقدة. وتوجد مجموعة واسعة من خوارزميات إدارة الذاكرة، ومعظمها يتطلب أشكالاً خاصة من دعم العتاد.
نفترض أن الذاكرة الرئيسية مصفوفة من البايتات القابلة للعنونة فردياً، ودورة تنفيذ التعليمات تولّد تدفقاً من عناوين الذاكرة. والعتاد المسؤول عن إدارة هذه العناوين هو وحدة إدارة الذاكرة (MMU)، ولا يمتلك أي قدرة على استنتاج غرض العنوان — فهو يتعامل مع الأرقام فقط.
نقطة أساسية أيضاً: التخزين العام الوحيد الذي يستطيع CPU الوصول إليه مباشرة هو الذاكرة الرئيسية والمسجلات؛ لا يستطيع المعالج الوصول مباشرة إلى القرص أو غيره من وسائط التخزين الطرفية. كما أن وصول CPU إلى الذاكرة الرئيسية أبطأ مرات عديدة من وصوله إلى المسجلات، وهنا يأتي دور الكاش الذي شرحناه في سلسلة المعمارية لتسريع الأمور.
الحماية بمسجلي الأساس والحد (Base & Limit Registers)
يجب أن يوفر العتاد آلية لحماية الذاكرة المخصصة لكل عملية، وتكليف نظام التشغيل بهذه المهمة وحده سيكون مكلفاً جداً في الأداء لدرجة عدم العملية.
آلية بسيطة للحماية:
- يخصص النظام للعملية P مدى متجاواراً واحداً من الذاكرة.
- مسجل الأساس (Base Register) يحمل أدنى عنوان مخصص لها.
- مسجل الحد (Limit Register) يحمل عدد بايتات هذا التخصيص.
باستخدام قيمتي هذين المسجلين، يفحص العتاد كل عنوان يولده البرنامج في وضع المستخدم (User Mode)، وأي محاولة للوصول إلى ذاكرة خارج الحدود تنتج فخاً (Trap) إلى النظام. وتغيير قيم هذين المسجلين تعليمات مميزة Privileged لا ينفذها إلا النواة — التي تحصل بالطبع على وصول غير مقيد لكل الذاكرة لأنها تحتاج ذلك لمهامها مثل تحميل البرامج وجلب معاملات الـ System Calls:
شكل (1): مسجلا الأساس والحد يحددان فضاء العناوين المنطقي
شكل (2): فحص العتاد لكل عنوان يولده البرنامج في وضع المستخدم
ربط العناوين (Address Binding)
العناوين في الكود المصدري تكون رمزية (Symbolic) — مثل اسم المتغير count. وعادة يربط المترجم هذه العناوين الرمزية بعناوين قابلة لإعادة التموضع (Relocatable) تُعطى كإزاحات من العنوان الأساسي للبرنامج، وقد تحول بعد ذلك إلى عناوين مطلقة (Absolute) بواسطة الرابط أو المحمّل. وللسماح بإعادة تموضع البرامج أثناء التشغيل من منطقة ذاكرة إلى أخرى، تستخدم الأنظمة الحديثة تقنيات خاصة تتطلب دعم العتاد ونظام التشغيل معاً.
العنوان المنطقي مقابل العنوان الفيزيائي
- العناوين التي يراها الـ CPU هي العناوين المنطقية (Logical) ويسمى أيضاً الافتراضي (Virtual).
- العناوين التي يراها مسجل عنوان الذاكرة (MAR) هي العناوين الفيزيائية (Physical).
قد يتطابق الفضاءان في بعض الأنظمة البسيطة، لكن في نمط الربط أثناء التنفيذ — وهو النمط السائد — يكونان منفصلين. وأثناء تنفيذ العملية، تتولى عتاد الـ MMU عملية الترجمة من العنوان المنطقي إلى الفيزيائي المطلوبة خلال دورة جلب/فك/تنفيذ. برنامج المستخدم يتعامل مع العناوين المنطقية حصراً، ولا تجري الـ MMU الترجمة إلا عند حدوث وصول فعلي للذاكرة.
في مثال بسيط: قد تترجم الـ MMU العناوين المنطقية في المدى من 0 إلى max إلى المدى R حتى R+max، حيث R قيمة مخزنة في مسجل إعادة التموضع (Relocation Register) الشبيه بمسجل الأساس:
شكل (3): الترجمة الديناميكية عبر مسجل إعادة التموضع
التحميل والربط الديناميكي
في التحميل الديناميكي (Dynamic Loading) لا تُحمَّل الروتينية (Routine) إلا عند استدعائها؛ فكل روتين له صورة على القرص بصيغة تحميل قابلة لإعادة التموضع، والروتينات التي لا تستدعى أبداً لا تُحمَّل أصلاً — مما قد يوفر قدراً كبيراً من الذاكرة. ويمكن تنفيذ ذلك من داخل برامج المستخدم دون مساعدة خاصة من العتاد أو النظام.
أما الربط الديناميكي (Dynamic Linking) فيؤجل الربط حتى وقت التنفيذ: يحمل نص البرنامج في الذاكرة Stub لكل مرجع إلى روتين مكتبة — وهو قطعة كود تخبرك أين تجد الروتين في الذاكرة أو القرص. عند أول تنفيذ للمصغّرة Stub تستبدل نفسها بعنوان الروتين وتنفذه. وبهذا تتشارك جميع العمليات نسخة واحدة من كل روتين مكتبة، لكن مشاركة الروتينات تحتاج مساعدة من العتاد والنظام (ذاكرة مشتركة).
التخصيص المتجاور (Contiguous Memory Allocation)
كان التخصيص المتجاور شائعاً في مراحل تطور أنظمة التشغيل الأولى، ومن الجيد فهمه لأنه يقدم قضايا التصميم التي تساعدك على تقدير مزايا الطرق الأحدث مثل التصفح Paging والتجزئة Segmentation.
في هذا النموذج تقيم كل عملية في مدى متجاوار واحد من الذاكرة (L عنواناً من B حتى B+L-1 مثلاً). وعادة يوجد قسمان في الذاكرة الفيزيائية: قسم لنظام التشغيل وقسم لعمليات المستخدم جميعاً.
وتكفي حماية الذاكرة هنا مخطط شبيه بمسجلي الأساس والحد: تعمل عملية المستخدم مع L عنواناً قانونياً من 0 حتى L-1، تفحص الـ MMU كل عنوان منطقي تولّده العملية للتأكد من أنه ضمن المدى القانوني، ثم تترجمه بإضافة قيمة مسجل إعادة التموضع. وبتغيير قيمتي المسجلين يستطيع النظام تتبع العمليات وهو يعيد تموضعها أو تغيير أحجامها.
تخصيص الأقسام
التقسيم الثابت الحجم (Fixed-Size Partitioning): يقسم النظام ذاكرة المستخدم إلى M قسماً متساوياً الحجم، ويخصص قسم واحد لكل عملية تريد التنفيذ. إذا كانت العملية أكبر من حجم القسم فمن المستحيل تشغيلها. وعند خروج العملية يعود قسمها إلى قائمة الأقسام الحرة.
التقسيم المتغير الحجم (Variable-Size Partitioning): أكثر مرونة: يحافظ النظام على قائمة حرة (Free-List) بالفتحات (Holes) المتاحة في الذاكرة. عندما تحتاج عملية إلى التحميل، يجد النظام — إن أمكن — فتحة تكفيها فيزيلها من القائمة ويضع العملية في بداية الفتحة، وأي فائض غير مستخدم يعد فتحة جديدة تعود إلى القائمة. وعند انتهاء العملية تتحرر ذاكرتها، ويفحص النظام إن كان يمكن دمج الذاكرة المحررة مع الفتحات المجاورة لتكوين فتحة أكبر:
شكل (4): الفتحات في التخصيص المتغير
وهنا تظهر مشكلة معروفة اسمها مشكلة التخزين الديناميكي: كيف نلبي طلباً بحجم N من قائمة الفتحات الحرة؟ لاستراتيجية البحث عن الفتحة تأثير في الأداء، ومنها ثلاث:
- First-Fit: اختر أول فتحة تكفي وتوقف عن البحث.
- Best-Fit: اختر أصغر فتحة تكفي — التي تترك أصغر فائض. (يمكن إبقاء القائمة مرتبة حسب الحجم لتسريع البحث.)
- Worst-Fit: اختر أكبر فتحة — التي تترك أكبر فائض.
وجدت بعض المحاكاات أن First-Fit وBest-Fit أسرع من Worst-Fit وكفءتان في تلبية المزيد من الطلبات، وأن First-Fit أسرع عموماً من Best-Fit — ولا توجد أفضلية واضحة بينهما في عدد الطلبات الملباة.
التشظي (Fragmentation)
التشظي نوعان:
• التشظي الخارجي (External Fragmentation): ذاكرة متاحة لكن غير قابلة للاستخدام — خاصة مجموعة فتحات كل واحدة صغيرة جداً للاستخدام، لكن مجموعها كان سيكفي لو أمكن ضمها في فتحة واحدة. ويحدث التشظي الخارجي الشديد حتماً عند استخدام أولى الاستراتيجيات الثلاث؛ فقد تضيع مثلاً ثلث الذاكرة بعد عدد كبير من عمليات التخصيص والتحرير.
• التشظي الداخلي (Internal Fragmentation): ذاكرة مخصصة لكن غير مستخدمة — قد تلزم طرق التخصيص إلى إعطاء العمليات ذاكرة أكثر من حاجتها (حد أدنى للتخصيص، أو تخصيص بدفعات بحجم محدد).
إذا كانت العمليات قابلة لإعادة التموضع ديناميكياً، استطاع النظام تحريكها لدمج التشظي الخارجي في فتحات صالحة — لكن هذه العملية (Compaction) مكلفة زمنياً إذا أجريت دفعة واحدة، وصعبة التصحيح إذا أجريت على دفعات.
والحل الأنيق — الذي سنراه الآن — هو «الالتفاف» حول مشكلة التشظي الخارجي كلياً بالسماح لتخصيص العملية أن يتكون من قطع ثابتة الحجم غير متجاورة من الذاكرة الفيزيائية تسمى الإطارات (Frames).
التصفح (Paging)
التصفح بديل للتخصيص المتجاور، ومعه لا يوجد تشظٍ خارجي إطلاقاً — وبالتالي لا حاجة للضغط Compaction.
الطريقة الأساسية
لنفرض أن أصغر وحدة قابلة للعنونة هي البايت، وأن العتاد يحدد حجم صفحة معيناً مثل 4KB (أي 4096 بايت). نقسم الذاكرة الرئيسية ومخزن النسخ الاحتياطي إلى قطع متجاورة بهذا الحجم تسمى الإطارات (Frames): الإطار رقم 0 يشغل البايتات من 0 حتى 4095، والإطار رقم 1 من 4096 حتى 8191، وهكذا:
شكل (5): عتاد التصفح
ينشئ نظام التشغيل مدخلاً في جدول الصفحات (Page Table) لكل صفحة عند تحميلها أول مرة في إطار: فالصفحة المنطقية i يوضع رقم الإطار المخصص لها في المدخل i من جدول صفحات العملية. وعندما تحاول العملية الوصول إلى الذاكرة، يستخدم العتاد بعض بتات العلوية من العنوان المنطقي — وتسمى رقم الصفحة (Page Number) — كمؤشر داخل جدول الصفحات.
يمكن تخيل العنوان المنطقي على شكل (p | d) حيث p بتات رقم الصفحة وd البتات المتبقية وتسمى الإزاحة (Offset). يجد العتاد في الموقع p من جدول الصفحات رقم الإطار f، ثم يشكل العنوان الفيزيائي (f | d) باستبدال p بـ f — وطول p وف d بالبتات يمكن أن يختلف — ويكمل الوصول إلى الذاكرة.
إذا كان حجم الصفحة 2 أس n بايتاً، فإن كل إزاحة تتكون من n بتاً. وإذا كان حجم الذاكرة المنطقية 2 أس m بايتاً، فإن رقم الصفحة يتكون من m-n بتاً.
المثال الرقمي المصغر:
شكل (6): ذاكرة منطقية 16 بايتاً وصفحات 4 بايتات
حجم الصفحة 2² = 4 بايتات، والذاكرة المنطقية 2⁴ = 16 بايتاً، والذاكرة الفيزيائية 2⁵ = 32 بايتاً. يترجم جدول الصفحات الصفحة المنطقية 0 إلى الإطار الفيزيائي 5، وهكذا. لنترجم العنوان المنطقي 13:
13 بالثنائي = 1101
الإزاحة d = 01
رقم الصفحة p = 11 = 3
جدول الصفحات : الصفحة 3 ← الإطار 2 = 10
العنوان الفيزيائي = (10 | 01) = 1001 = 9
ونرى القيمة المخزنة في العنوان 9 من الذاكرة الفيزيائية.
مع التصفح لا يوجد تشظٍ خارجي، لكن العملية عادة لا تحتاج كل ذاكرة «آخر إطار» لديها؛ فالباقي تشظٍ داخلي — بنصف صفحة في المتوسط. حجم الصفحة الصغير يقلل التشظي الداخلي، والحجم الكبير يجعل جدول الصفحات أصغر ويقلل حمل النسخ بين الذاكرة والمخزن الاحتياطي — وهي مقايضة كلاسيكية.
ولوضع عملية في الذاكرة الرئيسية يكتب النظام كودها وبنيات بياناتها في مجموعة إطارات لا يلزم أن تكون متجاورة، بينما يبقى فضاؤها المنطقي متجاواراً — مجرد مصفوفة بايتات من الصفر حتى الحد الأعلى.
الحماية مع التصفح مباشرة: النظام ينشئ جدول الصفحات ويستخدمه لحماية الذاكرة كما يستعمل غيره مسجلي الأساس والحد — ف«الأسس» هي أرقام الإطارات، و«الحدود» ضمنية تساوي حجم الصفحة. وليس أمام العملية سبيل لعنونة ذاكرة خارج جدول صفحاتها. كما يتتبع النظام كل تخصيصات الإطارات الفيزيائية عبر بنية اسمها Frame Table، ويحتفظ بنسخة من جدول صفحات كل عملية.
ومن المهم التمييز: حين يحتاج النظام نفسه ترجمة عنوان منطقي إلى فيزيائي (مثلاً عندما تمرر العملية عنواناً منطقياً كمعامل لطلب نظام كعنوان Buffer لعملية I/O)، يستخدم النسخة التي يملكها من جدول الصفحات لإجراء الترجمة «اليدوية». أما الترجمة الروتينية أثناء تنفيذ دورة الجلب/الفك/التنفيذ فيؤديها العتاد وليس نظام التشغيل.
دعم العتاد: مسجل PTBR والـ TLB
يمكن تنفيذ جداول الصفحات بطرائق متعددة. في أبسط الحالات قد يكون لكل عملية جدول صفحاتها الخاص من مسجلات مخصصة — لكن عدد المسجلات محدود فلا يصلح للجداول الكبيرة.
في كثير من الأنظمة الحديثة يحتوي معماري CPU/MMU على مسجل أساس جدول الصفحات (Page-Table Base Register – PTBR) يشير إلى جدول صفحات كبير مقيم في الذاكرة الرئيسية. وميزته أنه يسرّع تبديل السياق: تركيب جدول صفحات العملية الجديدة لا يتطلب سوى تغيير قيمة مسجل واحد.
لكن لجدول الصفحات المقيم في الذاكرة عيب: كل وصول للذاكرة يتطلب وصولين — الأول لاستخراج رقم الإطار من الجدول، والثاني لجلب البيانات المطلوبة فعلاً.
لتجنب إبطاء الوصول للذاكرة إلى النصف، تستخدم الأنظمة الحديثة كاش عناوين سريعاً من ذاكرة ترابطية اسمه Translation Look-Aside Buffer (TLB) حتى لا تضطر الـ MMU غالباً لوقت الوصول إلى جدول الصفحات عند الترجمة:
شكل (7): عتاد التصفح مزوداً بالـ TLB
يفحص العتاد الـ TLB أولاً عند الترجمة؛ فإن كانت هناك إصابة (Hit) اكتملت الترجمة فوراً، وإن كانت إخفاقاً (Miss) جرى الرجوع لجدول الصفحات وإدراج المعلومة في الـ TLB للاستخدام المستقبلي — فإن كان ممتلئاً استبدل مدخل قديم بمدخل جديد. وتسمح تقنية معرف فضاء العناوين (ASID) للـ TLB بأن يحوي معلومات ترجمة لعدة عمليات مختلفة في آن واحد، مما يقلل الحاجة إلى تفريغ الكاش المكلف عند تبديل السياق.
زمن الوصول الفعال (Effective Access Time – EAT) دالة في نسبة الإصابة وزمن الوصول للذاكرة وزمن بحث الـ TLB. مثلاً: نسبة إصابة 90% وزمن وصول للذاكرة 12 نانوثانية:
EAT = 0.9 × 12 + 0.1 × 24 = 13.2 ns
لاحظ الأثر: بدون TLB كنا سنضاعف الزمن، ومع نسبة إصابة عالية اقتربنا من الزمن الأصلي.
الحماية والصفحات المشتركة
بعض بتات مداخل جدول الصفحات (PTEs) تستخدم لقيود الوصول — بت القراءة فقط Read-Only مثلاً، حيث يولد العتاد فخاً إذا حاولت عملية كتابة صفحة للقراءة فقط. ومن الشائع وجود بت صلاحية Valid Bit؛ وبعض الأنظمة تجعل جدول الصفحات بطول يوازي حجم العملية فقط مع مسجل طول جدول الصفحات (PTLR)، فمحاولة الوصول «بعد نهاية الجدول» تولد فخاً. وللأسف يمكن للعملية عموماً الوصول إلى الجزء الداخلي غير المستخدم من آخر صفحة لديها — تشظينا الداخلي.
ويدعم نموذج التصفح الذاكرة المشتركة بسهولة: إذا احتوى جدولا صفحات لعمليتين على رقم الإطار نفسه فتستطيعان مشاركة ذلك الإطار. ويستخدم النظام هذا لتشارك نص برنامج للقراءة فقط بين عمليات كثيرة — مثل مكتبة C القياسية — كما يمكن مشاركة ذاكرة قابلة للكتابة وسيلة للتواصل بين العمليات.
بنية جدول الصفحات (Structure of the Page Table)
جداول الصفحات الحديثة كبيرة! لنرَ لماذا ونماذا:
مدخل جدول الصفحات الشائع حجمه 4 بايتات، وحجم الصفحة النموذجي 2¹² = 4KB، فتتسع الصفحة الواحدة لألف مدخل جدول (1024 مدخلاً). وفي فضاء عناوين 32-bit يوجد 2³² بايتاً قابلة للعنونة، فمع صفحات 4KB يبقى 20 بتاً لرقم الصفحة، أي ما يصل إلى 2²⁰ صفحة — قرابة المليون صفحة لكل عملية!
وبهذه الافتراضات سيحتوي جدول صفحات العملية 2²² بايتاً، أي أنه يمتد بنفسه فوق 2¹⁰ = 1024 صفحة. ولتجنب حل مشكلة التخصيص الديناميكي من أجل تخصيص جدول الصفحات نفسه، يمكن «تصفَّح» جداول الصفحات أيضاً.
التصفح الهرمي (Hierarchical Paging)
في أحد المخططات يقسم العنوان المنطقي إلى (P1 | P2 | d):
- يستخدم P1 كمؤشر في جدول الصفحات الخارجي.
- المدخل الموجود هو رقم إطار إحدى صفحات جدول الصفحات نفسه.
- ثم يستخدم P2 وd بالطريقة الاعتيادية لإكمال الترجمة: P2 مؤشر في تلك الصفحة من الجدول، ورقم الإطار الناتج يدمج مع d لتكوين العنوان الفيزيائي:
شكل (8): مخطط جدول صفحات من مستويين
ولجداول أكبر دعمت بعض المعماريات مستويات أكثر — بعض معالجات SPARC دعم ثلاثة مستويات، وMotorola 68030 أربعة. أما فضاءات 64-bit فلا يعتبر مناسباً رسمها بهذه الجداول التقليدية الهرمية؛ لأنه يتطلب عدداً مفرطاً من المستويات — سبعة مستويات مثلاً.
جداول الصفحات المهاشة (Hashed Page Tables)
بديل لكل عملية: يطبق دالة هاش على العنوان الافتراضي، وتحل التصادمات بالتسلسل الخارجي (External Chaining)؛ كل مدخل في السلسلة يحوي عنواناً افتراضياً ورقم إطار ومؤشراً للمدخل التالي. ونسخة منه اسمها الجداول المجمعة (Clustered) يجعل كل مدخل يشير إلى عدة صفحات دفعة واحدة.
جداول الصفحات المقلوبة (Inverted Page Tables)
أنظمة مثل UltraSPARC وPowerPC استخدمت ابتكاراً اسمه الجدول المقلوب: مدخل واحد لكل إطار — وليس لكل صفحة افتراضية — يحدد أي «فضاء عناوين» (أي عملية) يستخدم الإطار ولأي رقم صفحة افتراضية. ويوجد جدول مقلوب واحد للنظام كله، وليس واحداً لكل عملية:
شكل (9): بنية جدول الصفحات المقلوب
الميزة البارزة: مقدار الذاكرة المستخدمة للجدول محدود بثابت مضروب في حجم الذاكرة الفيزيائية — بدل أن يكون محدوداً بعدد العمليات وحجم أكبر فضاء افتراضي. والعيب البارز: لا يمكن فهرسة الجدول مباشرة برقم الصفحة، فقد يستغرق البحث عن المدخل الصحيح للترجمة الأمامية وقتاً طويلاً — بينما يدعم هذا الهيكل الترجمة العكسية بكفاءة. ولذا يستخدم معه فكرة الجداول المهاشة لتسريع البحث: تطبق دالة الهاش على معرف فضاء العناوين والعنوان الافتراضي لتحديد موقع أول فحص، ثم تتبع السلاسل الخارجية حتى إيجاد المدخل المطابق. وبطبيعة الحال، عند إصابة الـ TLB لا يرجع أحد للجدول أصلاً ويقارب زمن الوصول الفعال زمن الوصول للذاكرة نفسه.
التبديل (Swapping)
التبديل القياسي: فكرته سحب الذاكرة الرئيسية مؤقتاً من عملية لإعطائها لعملية أخرى: إذا سحبنا الذاكرة من العملية X نسخنا أولاً محتوياتها (النص والبيانات ومعظم معلومات السياق) إلى التخزين الثانوي — نقول إن X أخرجت Swap Out — ثم أعطينا الذاكرة لعمليات أخرى. ويحتفظ النظام بما يكفي من معلومات X ليتمكن لاحقاً من إيجادها وإعادتها إلى الذاكرة (Swap In) لاستئناف تنفيذها. ونظام يستطيع التبديل يستطيع تعدد برمجة عمليات أكثر مما يتسع في الذاكرة الفيزيائية دفعة واحدة. والعمليات الخاملة منذ زمن طويل مرشحة جيدة للإخراج.
لكن التبديل القياسي غير عملي في الأنظمة الحديثة لأن إخراج وإدخال عمليات كاملة يستغرق وقتاً طويلاً؛ والأكثر شيوعاً التبديل على مستوى الصفحات — إخراج وإدخال صفحات مفردة من العملية، فمن النادر جداً أن يُخرج أكثر من نسبة صغيرة من صفحات أي عملية في لحظة ما.
والأنظمة المحمولة؟ لا تجري تبديلاً عادة للأسباب التالية:
- التبديل يتطلب وسائط تخزين ثانوية كبيرة والمحمولات تفتقر إليها.
- معدل النقل بين الذاكرة الرئيسية وذاكرة الفلاش بطيء.
- التبديل يستنزف سريعاً العدد المحدود من دورات الكتابة التي يدعمها الفلاش.
بدل التبديل: يطلب iOS من التطبيقات التخلي عن الذاكرة غير الضرورية، وقد ينهي العمليات التي لا تحرر ما يكفي. ويتصرف Android بالمثل، إلا أنه قبل قتل العملية بسبب الاستخدام المفرط يحفظ حالتها على الذاكرة الثانوية ليستأنفها بسرعة. ولهذا على مبرمجي البيئات المحمولة دمج عادات توفيرية في تخصيص الذاكرة وتحريرها داخل تطبيقاتهم.
أمثلة واقعية سريعة
IA-32 (Intel 32-bit): تجمع بين التجزئة والتصفح: العنوان المنطقي زوج (Selector, Offset)، ووحدة التجزئة — جزء من الـ MMU — تحوله إلى عنوان خطي (Linear Address) بإضافة الإزاحة إلى أساس القطعة (وإن تجاوزت الإزاحة الحد وقع فخ)، ثم تقوم وحدة التصفح بترجمة الخطي إلى فيزيائي:
شكل (10): ترجمة العنوان المنطقي إلى الفيزيائي في IA-32
شكل (11): وحدة التجزئة في IA-32
يدعم حجمَي صفحة: 4KB و4MB عبر علم Page Size Flag في الجدول الخارجي — إن لم يضبط جرت ترجمة هرمية من مستويين، وإن ضبط جرت ترجمة أحادية المستوى متجاوزة الجدول الداخلي:
شكل (12): وحدة التصفح في IA-32
x86-64: طورته AMD وتبناه Intel، ويدعم نظرياً فضاءات 64-bit، والأنظمة الحالية تستخدمه لعناوين افتراضية حتى 48 بتاً وفيزيائية حتى 52 بتاً.
ARMv8: المعمارية الشائعة في المحمولات، وتدعم صفحات 4KB و16KB و64KB، وأقساماً متجاورة (Regions) بحجم 2MB و1GB و32MB و512MB، وتملك مستويين من الـ TLB: TLBs مصغرة داخلية منفصلة للتعليمات والبيانات تدعم ASIDs، وإن حدث إخفاق فيها جرى الرجوع إلى TLB رئيسية خارجية، وإن لزمت جولات في جداول الصفحات (Page Walks) نفذها عتاد ARM بنفسه:
شكل (13): التصفح الهرمي رباعي المستويات في ARMv8
بهذا تكون قد فهمت كيف يدير نظام التشغيل الذاكرة من التخصيص البدائي المتجاور إلى التصفح الحديث وترجمة العناوين عبر الـ TLB. نلتقي في الدرس القادم بإذن الله.
لا تنسونا من صالح دعائكم.