Mohammed Mohsen | محمد محسن
Mohammed Mohsen | محمد محسن

@mhmdvoid

15 تغريدة 19 قراءة Feb 26, 2022
هل قد تسألت ماهي ادارة ذاكرة الحاسب الخاصه بالبرامج والمترجم؟ لست أقصد كيف يدير نظام التشغيل Ram (paging & swapping ) فهذا موضوع اخر.
سلسلة تعنى بشرح كيف برنامجك/كودك يستخدم الذاكره ، وكيف المترجم "compiler" يصمم "layout" القسم الخاص بكل برنامج.
راح اتكلم عن Allocators عامةً
ملاحظة: سوف اتجاهل اغلب تفاصيل العتاد HW، حجم Page.
Alignement الخاصه بالمعمارية
Virtual addressing, Virtual Disk.
سوف اذكر malloc, free وكيف memory allocator تعمل، وخصوصا Stack Allocation
Heap Allocation
Global/Static Allocation.
كل برنامج لديه جزء من ذاكرة Ram من قبل النظام
كيف يتم تحديد الجزء ومن اين يبدا الAddress لهذا الجزء كلها تفاصيل نظام التشغيل ومسؤوليته.
الصورة : توضيح للجزء الخاص الذي يملكه كل برنامج داخل ذاكرة الحاسب او RAM
عباره عن 3 اقسام رئيسية:
- Stack seg
- Data seg
- Text Seg الكود
كل برنامج يحتوي على اوامر(code) وبيانات لذلك نحتاج
ذاكره لتخزين هذه البيانات والاوامر، ولكن حجم البيانات، وانواعها تختلف.
في قسم text seg هنا يتم وضع جميع الاوامر الخاصه بالبرنامج، مثال
5 + 4
لو افترضنا ان هذا الامر بعد التحويل الى Binary
0000011000110001 هذا الرقم سيتم تخزينه في مكان معين(عنوان) من ضمن Text seg
قسم Stack seg يتم تخزين بيانات ذات حجم ثابت Fixed/known size.
مثال :
boolean, int, char, etc...
هذه البيانات حجمها ثابت، int 32 bit , boolean 8 bit, char 8/16 bits وهكذا لذلك هذه البيانات يتم تخزينها بشكل ثابت(static) وغالبا المتغيرات داخل الدوال والباراميتر في الدوال.
int main(int foo) {
char c = 'a';
}
المتغير "foo" و "c" احجامهم وقيمهم دائما معلومه وثابته لذلك يتم تخزينهم في Stack.
فيه معلومه جدا مهمه، لتخزين البيانات انت 1- تحتاج مساحة وتحتاج طريقة 2-لارجاع هذه المساحه للنظام حتى يتم استخدامها مره اخرى عند الحاجه.
في Stack seg تلقائياً عند تعريفك لمتغير مثل "c" او "foo" سوف يتم حجز مساحة لوضع القيم، وعند الخروج من نطاق الداله (scope) سوف يتم ارجاع هذه المساحه للنظام ويكون جاهز لاستقبال قيم جديده، لاحظ المعلومات الموجوده في الاعلى تحققت..تمكننا من حجز وارجاع المساحه ! رائع. لاحظ تلقائياً !!
انت لم تعمل شي لحجز المساحه او ارجاعها للنظام.
للاسف ليست كل البيانات معروفه compile-time, مثال: ماذا لو طلبت منك استقبال بيانات من المستخدم (user input) ؟ حينها لن نعرف حجم البيانات حتى نشغل البرنامج Run-time وبالتالي البيانات تكون unknown size حجم غير ثابت ! اين نخزنها؟ وكيف ؟
الجواب موجود في الصورة ، هنالك جزء يسمى Data Seg.
المترجم (Compiler) دايماً يقدم لك stdlib يوجد بها طريقة لحفظ هذه البيانات at runtime : في C (malloc)
Java (Garbage collector)
Swift (ARC)
لنأخذ C malloc
هذه الدالة تمكنك من حجز مكان في الذاكر بشكل ديناميك في وقت التنفيذ unknown)
بمعنى Allocators
تعمل Linked list يتم تخزينهم في DataSeg وهذه LinkedList تعمل على توفير مساحة لهذه البيانات في وقت التنفيذ .
لذلك عند عمل مترجم ، تحتاج تعمل Allocation لGlobal data , Stack allocation .
وبعد ذلك تعمل Malloc باستخدام Global Data ومن ثم تسمية الجزء المستخدم من قبل malloc بـ heap
لو افترضنا اني بعمل malloc
Block Head
Block *FreeList
SafePtr malloc(LargeEnough size) { … }
لاحظ Head و FreeList
سوف يتم تخزينهم في Global data اين يتم وضعهم؟ في Data segment الان لو اردت طلب 1KB هذه LinkedList سوف تحجز لي من DataSeg (لانها اساساً مخزنه في هذا الجزء) الحجم.
البعض يسأل لماذا احتاج malloc ، لماذا لا اخزن جميع classes + runtime data بنفسي في global data يعني هكذا مثلاً
MyClass *class = null
void init() {…}
بامكانك واحياناً يكون اسرع بس uninitialized بالاضافه الى انه لن تستفيد من الذاكره بافضل طريقة وهذا ماتوفره الـAllocators
يعملون طبقة من الـ Abstraction/Management بحيث :
تتبع الاماكن الفارغه في Data Seg وتتواصل مع نظام التشغيل لجلب مزيد من الذاكره وامور اخرى.
أخيراً، data seg له حجم معين وينتهي بعدها ثم نبدا نطلب من نظام التشغيل بجلب ذاكرة من Virtual memory (disk) وتعمل Swapping
هذا يجيب على سؤالي القديم هل malloc فقط تحجز عدد معين مثلاً 1GB او 2GB ؟
الاجابة لا طبعاً بامكانك حجز ذاكره حتى تمتلي RAM + Virtual Memory .
وهذا يعرف Virtual memory technique بحيث حجم البرنامج اكبر من حجم الذاكره.
انتهى، المعذره كنت مشغول الفترة الماضيه.

جاري تحميل الاقتراحات...