سؤال

لقد كنت أقرأ عن ظروف الذاكرة على لينكس، وفصلتني الفقرة التالية من صفحات الرجل:

بشكل افتراضي، يتبع Linux استراتيجية تخصيص الذاكرة المتفائلة. هذا يعني أنه عند إرجاع Malloc () غير الفارغة، لا يوجد ضمان أن الذاكرة متوفرة حقا. هذا خطأ سيء حقا. في حال اتضح أن النظام خارج الذاكرة، سيتم قتل عملية أو أكثر من قبل قاتل Oom السلبي. [...

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

هل كانت مفيدة؟

المحلول

هذا يعتمد؛ يمكنك تكوين إعدادات OverCommit في Kernel باستخدام vm.overcommit_memory.

ناقش عشب صوفي قبل بضع سنوات كيف هذا السلوك هو في الواقع غير مشغول إلى معيار C ++:

"في بعض أنظمة التشغيل، بما في ذلك نظام التشغيل على وجه التحديد، تنجح تخصيص الذاكرة دائما. توقف الكامل. كيف يمكن أن تنجح التخصيص دائما، حتى عندما تكون الذاكرة المطلوبة حقا غير متوفرة؟ السبب هو أن التخصيص نفسه يسجل مجرد طلب للذاكرة؛ تحت الأغطية، لا تلتزم الذاكرة (الجسدية أو الظاهرية) في الواقع بالعملة الطالبة، مع متجر دعم حقيقي، حتى يتم استخدام الذاكرة بالفعل.

"لاحظ أنه إذا كان الجديد يستخدم مرافق نظام التشغيل مباشرة، فسوف ينجح الجديد دائما ولكن أي رمز بريء لاحق مثل BUF [100] = 'C'؛ يمكن أن يرمي أو تفشل أو تفشل. من وجهة نظر قياسية C ++، كلاهما غير مظونة، لأن معيار C ++ يتطلب أنه إذا كان الجديد لا يستطيع ارتكاب ذاكرة كافية، فيجب أن تفشل (هذا لا)، وهذا الرمز مثل BUF [100] = "C" يجب ألا يرمي استثناء أو فشله بطريقة أخرى (هذا ربما)."

نصائح أخرى

لا يمكنك التعامل معها في برنامجك، نقي وبسيط.

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

ولكن كما ترى، كل هذا يحدث داخل النواة، لا يمكن تطبيقك أن يرى ذلك. إذا كان النظام الحرج، فيمكنك تعطيل OverCommit AllTogether على النظام.

أعتقد أن malloc لا يزال بإمكانه إرجاع فارغة. السبب في أن هناك فرقا بين ذاكرة النظام المتاحة (RAM + Swap) والمبلغ في مساحة عنوان العملية الخاصة بك.

على سبيل المثال، إذا طلبت 3GB من الذاكرة من Malloc على Linux X86 قياسي، فسيؤدي ذلك بالتأكيد فارغة لأن هذا أمر مستحيل على إعطاء مقدار الذاكرة المعطى لتطبيقات مساحة المستخدم.

سامحني إذا كنت مخطئا، لكنني لن أحاول الخروج من الذاكرة المخصصة تكون كافية لضمان أن يكون لديك كل بايت واحد طلبته؟ أو حتى الكتابة فقط إلى البايت الأخير، فإنه سوف يرمي استثناء إذا كانت الذاكرة لم تكن حقا لك الحق؟

إذا كان هذا صحيحا، فيمكنك فقط أن تجرب الكتابة إلى البايت الأخير (والأول؟) بايت من الذاكرة ومعرفة ما إذا كان يعمل بشكل جيد، وإذا لم يكن بإمكانك إرجاع NULL من Malloc.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top