في أجهزة الكمبيوتر ، لكي تكون العملية قابلة للتنفيذ ، يجب وضعها في الذاكرة. لهذا ، يجب تعيين حقل لعملية في الذاكرة. يعد تخصيص الذاكرة أمرًا مهمًا يجب أن تكون على دراية به ، خاصة في بنى kernel والنظام.

دعنا نلقي نظرة على تخصيص ذاكرة Linux بالتفصيل ونفهم ما يجري وراء الكواليس.

كيف يتم تخصيص الذاكرة؟

لا يعرف معظم مهندسي البرمجيات تفاصيل هذه العملية. ولكن إذا كنت مرشحًا لمبرمج نظام ، فيجب أن تعرف المزيد عنه. عند النظر في عملية التخصيص ، من الضروري الخوض في القليل من التفاصيل حول Linux و غليبك مكتبة.

عندما تحتاج التطبيقات إلى ذاكرة ، يجب أن تطلبها من نظام التشغيل. سيتطلب هذا الطلب من kernel بشكل طبيعي استدعاء نظام. لا يمكنك تخصيص الذاكرة بنفسك في وضع المستخدم.

ال مالوك () عائلة الوظائف هي المسؤولة عن تخصيص الذاكرة بلغة C. السؤال الذي يجب طرحه هنا هو ما إذا كان malloc () ، كدالة glibc ، يقوم بإجراء مكالمة نظام مباشرة.

لا يوجد استدعاء لنظام يسمى malloc في نواة لينكس. ومع ذلك ، هناك نوعان من استدعاءات النظام لمطالب ذاكرة التطبيقات ، وهما brk و mmap.

نظرًا لأنك ستطلب ذاكرة في تطبيقك عبر وظائف glibc ، فقد تتساءل عن أي من مكالمات النظام هذه يستخدمها glibc في هذه المرحلة. الجواب كلاهما.

instagram viewer

استدعاء النظام الأول: brk

كل عملية لها حقل بيانات متجاور. مع استدعاء نظام brk ، يتم زيادة قيمة فاصل البرنامج ، التي تحدد حد حقل البيانات ، ويتم تنفيذ عملية التخصيص.

على الرغم من أن تخصيص الذاكرة بهذه الطريقة سريع جدًا ، إلا أنه ليس من الممكن دائمًا إعادة المساحة غير المستخدمة إلى النظام.

على سبيل المثال ، ضع في اعتبارك أنك تخصص خمسة حقول ، حجم كل منها 16 كيلو بايت ، مع استدعاء نظام brk عبر وظيفة malloc (). عندما تنتهي من الرقم الثاني من هذه الحقول ، لا يمكن إرجاع المورد ذي الصلة (إلغاء التخصيص) حتى يتمكن النظام من استخدامه. لأنه إذا قمت بتقليل قيمة العنوان لإظهار المكان الذي يبدأ منه الحقل الثاني الخاص بك ، مع استدعاء إلى brk ، فستكون قد قمت بإلغاء تخصيص الحقول رقم ثلاثة وأربعة وخمسة.

لمنع فقدان الذاكرة في هذا السيناريو ، يراقب تنفيذ malloc في glibc الأماكن المخصصة في حقل بيانات العملية و ثم يحدد لإعادته إلى النظام باستخدام وظيفة free () ، بحيث يمكن للنظام استخدام المساحة الخالية لمزيد من الذاكرة المخصصات.

بمعنى آخر ، بعد تخصيص خمس مناطق بحجم 16 كيلو بايت ، إذا تم إرجاع المنطقة الثانية بالوظيفة المجانية () ومنطقة أخرى بحجم 16 كيلو بايت يُطلب مرة أخرى بعد فترة ، بدلاً من توسيع منطقة البيانات من خلال استدعاء نظام brk ، يتم إرجاع العنوان السابق.

ومع ذلك ، إذا كانت المساحة المطلوبة حديثًا أكبر من 16 كيلو بايت ، فسيتم تكبير منطقة البيانات عن طريق تخصيص منطقة جديدة باستخدام استدعاء نظام brk نظرًا لعدم إمكانية استخدام المنطقة الثانية. على الرغم من أن المنطقة الثانية ليست قيد الاستخدام ، لا يمكن للتطبيق استخدامها بسبب اختلاف الحجم. بسبب سيناريوهات كهذه ، هناك موقف يسمى التجزئة الداخلية ، وفي الواقع ، نادرًا ما يمكنك استخدام جميع أجزاء الذاكرة على أكمل وجه.

لفهم أفضل ، حاول تجميع وتشغيل التطبيق النموذجي التالي:

#تضمن <stdio.h>
#تضمن <stdlib.h>
#تضمن <unistd.h>
intالأساسية(int أرجك شار* argv [])
{
شار * ptr [7];
int ن؛
printf ("Pid لـ٪ s:٪ d"، argv [0]، getpid ())؛
printf ("فاصل البرنامج الأولي:٪ p"، sbrk (0)) ؛
لـ (ن = 0 ؛ ن<5; n ++) ptr [n] = malloc (16 * 1024) ؛
printf ("بعد 5 × 16 كيلو بايت malloc:٪ p"، sbrk (0)) ؛
مجانا(ptr[1]);
printf ("بعد التخلص من الثانية 16 كيلو بايت:٪ p"، sbrk (0)) ؛
ptr [5] = malloc (16 * 1024) ؛
printf ("بعد تخصيص 6 من 16kB:٪ p"، sbrk (0)) ؛
مجانا(ptr[5]);
printf ("بعد تحرير الكتلة الأخيرة:٪ p"، sbrk (0)) ؛
ptr [6] = malloc (18 * 1024) ؛
printf ("بعد تخصيص 18 كيلو بايت جديد:٪ p"، sbrk (0)) ؛
getchar () ؛
إرجاع0;
}

عند تشغيل التطبيق ستحصل على نتيجة مشابهة لما يلي:

رقم Pid of ./a.out: 31990
البرنامج الأولي فترة راحة: 0x55ebcadf4000
بعد 5 × 16 كيلو بايت malloc: 0x55ebcadf4000
بعد التخلص من الثانية 16 كيلو بايت: 0x55ebcadf4000
بعد تخصيص 6 من 16 كيلو بايت: 0x55ebcadf4000
بعد تحرير آخر كتلة: 0x55ebcadf4000
بعد تخصيص أ الجديد18كيلوبايت: 0x55ebcadf4000

سيكون ناتج brk مع دعامة كما يلي:

brk (باطل) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000

كما ترى، 0x21000 تمت إضافته إلى عنوان النهاية لحقل البيانات. يمكنك فهم هذا من القيمة 0x5608595d7000. تقريبًا 0x21000، أو تم تخصيص 132 كيلوبايت من الذاكرة.

هناك نقطتان مهمتان يجب مراعاتهما هنا. الأول هو تخصيص أكثر من المبلغ المحدد في نموذج التعليمات البرمجية. آخر هو أي سطر من الكود تسبب في استدعاء brk الذي وفر التخصيص.

ترتيب مساحة العنوان العشوائية: ASLR

عند تشغيل التطبيق المثال أعلاه واحدًا تلو الآخر ، سترى قيم عناوين مختلفة في كل مرة. يؤدي تغيير مساحة العنوان بشكل عشوائي بهذه الطريقة إلى تعقيد عمل الهجمات الأمنية ويزيد من أمان البرامج.

ومع ذلك ، في معماريات 32 بت ، يتم استخدام ثماني بتات بشكل عام لعشوائية مساحة العنوان. لن تكون زيادة عدد البتات مناسبة لأن المنطقة القابلة للعنونة على البتات المتبقية ستكون منخفضة جدًا. كما أن استخدام مجموعات 8 بت فقط لا يجعل الأمور صعبة بما يكفي للمهاجم.

من ناحية أخرى ، في معماريات 64 بت ، نظرًا لوجود عدد كبير جدًا من البتات التي يمكن تخصيصها لعملية ASLR ، يتم توفير عشوائية أكبر بكثير ، وزيادة درجة الأمان.

Linux kernel قوى أيضًا الأجهزة التي تعمل بنظام Android ويتم تنشيط ميزة ASLR بالكامل على Android 4.0.3 والإصدارات الأحدث. حتى لهذا السبب وحده ، لن يكون من الخطأ القول إن الهاتف الذكي 64 بت يوفر ميزة أمنية كبيرة على إصدارات 32 بت.

من خلال تعطيل ميزة ASLR مؤقتًا باستخدام الأمر التالي ، سيظهر أن تطبيق الاختبار السابق يُرجع قيم العنوان نفسها في كل مرة يتم تشغيله فيها:

صدى صوت0 | sudo tee / proc / sys / kernel / randomize_va_space

لاستعادته إلى حالته السابقة ، يكفي كتابة 2 بدلاً من 0 في نفس الملف.

استدعاء النظام الثاني: mmap

mmap هو استدعاء النظام الثاني المستخدم لتخصيص الذاكرة على Linux. باستخدام مكالمة mmap ، يتم تعيين المساحة الخالية في أي منطقة من الذاكرة إلى مساحة العنوان لعملية الاستدعاء.

في تخصيص الذاكرة الذي تم القيام به بهذه الطريقة ، عندما تريد إرجاع قسم 16 كيلو بايت الثاني باستخدام الوظيفة free () في مثال brk السابق ، فلا توجد آلية لمنع هذه العملية. تتم إزالة مقطع الذاكرة ذي الصلة من مساحة العنوان للعملية. تم وضع علامة عليه على أنه لم يعد مستخدمًا وإعادته إلى النظام.

نظرًا لأن عمليات تخصيص الذاكرة باستخدام mmap بطيئة جدًا مقارنة بتلك التي تحتوي على brk ، فإن تخصيص brk مطلوب.

باستخدام mmap ، يتم تعيين أي مساحة خالية من الذاكرة إلى مساحة العنوان للعملية ، لذلك تتم إعادة تعيين محتويات المساحة المخصصة قبل اكتمال هذه العملية. إذا لم تتم إعادة التعيين بهذه الطريقة ، فيمكن أيضًا الوصول إلى البيانات التي تنتمي إلى العملية التي استخدمت سابقًا منطقة الذاكرة ذات الصلة من خلال العملية التالية غير ذات الصلة. هذا من شأنه أن يجعل من المستحيل التحدث عن الأمن في الأنظمة.

أهمية تخصيص الذاكرة في Linux

يعد تخصيص الذاكرة أمرًا مهمًا للغاية ، لا سيما في قضايا التحسين والأمان. كما هو موضح في الأمثلة أعلاه ، فإن عدم الفهم الكامل لهذه المشكلة قد يعني تدمير أمان نظامك.

حتى المفاهيم المشابهة لـ push and pop الموجودة في العديد من لغات البرمجة تعتمد على عمليات تخصيص الذاكرة. تعد القدرة على استخدام ذاكرة النظام وإتقانها جيدًا أمرًا حيويًا في كل من برمجة النظام المضمنة وفي تطوير بنية نظام آمنة ومحسّنة.

إذا كنت تريد أيضًا أن تغمس أصابعك في تطوير Linux kernel ، ففكر في إتقان لغة البرمجة C أولاً.

مقدمة موجزة عن لغة البرمجة سي

اقرأ التالي

شاركسقسقةشاركبريد الالكتروني

مواضيع ذات صلة

  • لينكس
  • ذاكرة الكمبيوتر
  • نواة لينكس

نبذة عن الكاتب

فاتح كوجوكاراكورت (7 مقالات منشورة)

مهندس ومطور برمجيات من محبي الرياضيات والتكنولوجيا. لطالما أحب الكمبيوتر والرياضيات والفيزياء. لقد طور مشاريع محركات الألعاب بالإضافة إلى التعلم الآلي والشبكات العصبية الاصطناعية ومكتبات الجبر الخطي. علاوة على ذلك ، يواصل العمل على التعلم الآلي والمصفوفات الخطية.

المزيد من Fatih Küçükkarakurt

اشترك في نشرتنا الإخبارية

انضم إلى النشرة الإخبارية لدينا للحصول على نصائح تقنية ومراجعات وكتب إلكترونية مجانية وصفقات حصرية!

انقر هنا للاشتراك