سؤال

لقد بحثت في Google ووجدت أن معظم الأشخاص يؤيدون استخدام kmalloc, ، حيث نضمن لك الحصول على كتل فعلية متجاورة من الذاكرة.ومع ذلك، يبدو الأمر كذلك أيضًا kmalloc يمكن أن تفشل إذا كانت متجاورة بدني لا يمكن العثور على الكتلة التي تريدها.
ما هي مزايا وجود كتلة متجاورة من الذاكرة؟على وجه التحديد، لماذا أحتاج إلى الحصول على متجاورة بدني كتلة من الذاكرة في مكالمة النظام؟هل هناك أي سبب لعدم تمكني من استخدامه vmalloc?
أخيرًا، إذا كنت سأقوم بتخصيص الذاكرة أثناء معالجة مكالمة النظام، فهل يجب أن أحدد ذلك GFP_ATOMIC؟هل يتم تنفيذ استدعاء النظام في سياق ذري؟

GFP_ATOMIC
التخصيص عالي الأولوية ولا ينام.هذا هو العلم الذي يجب استخدامه في معالجات المقاطعة والنصفين السفلي والمواقف الأخرى التي لا يمكنك النوم فيها.

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

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

المحلول

ما عليك سوى القلق بشأن استخدام الذاكرة المتجاورة فعليًا إذا كان سيتم الوصول إلى المخزن المؤقت بواسطة جهاز DMA على ناقل موجه فعليًا (مثل PCI).تكمن المشكلة في أن العديد من استدعاءات النظام ليس لديها طريقة لمعرفة ما إذا كان سيتم تمرير المخزن المؤقت الخاص بها في النهاية إلى جهاز DMA:بمجرد تمرير المخزن المؤقت إلى نظام فرعي آخر للنواة، لا يمكنك حقًا معرفة إلى أين سيذهب.حتى لو كانت النواة لا تستخدم المخزن المؤقت لـ DMA اليوم، التطور المستقبلي قد يفعل ذلك.

غالبًا ما يكون vmalloc أبطأ من kmalloc، لأنه قد يتعين عليه إعادة تعيين مساحة المخزن المؤقت إلى نطاق متجاور تقريبًا.لا يتم إعادة تعيين kmalloc أبدًا، على الرغم من أنه إذا لم يتم استدعاؤه باستخدام GFP_ATOMIC، فيمكن أن يتم حظر kmalloc.

إن kmalloc محدود في حجم المخزن المؤقت الذي يمكن أن يوفره:128 كيلو بايت*).إذا كنت بحاجة إلى مخزن مؤقت كبير حقًا، فيجب عليك استخدام vmalloc أو بعض الآليات الأخرى مثل حجز ذاكرة عالية عند التمهيد.

*) كان هذا صحيحًا بالنسبة للنوى السابقة.في النوى الحديثة (لقد اختبرت ذلك في 2.6.33.2)، يصل الحد الأقصى لحجم kmalloc الواحد إلى 4 ميجابايت!(كتبت إلى حد ما وظيفة مفصلة عن هذا.) - كيوان

بالنسبة لاستدعاء النظام، لا تحتاج إلى تمرير GFP_ATOMIC إلى kmalloc()، ويمكنك استخدام GFP_KERNEL.أنت لست معالج المقاطعة:يدخل رمز التطبيق إلى سياق النواة عن طريق المصيدة، وهو ليس مقاطعة.

نصائح أخرى

اجابة قصيرة:تحميل برامج تشغيل الأجهزة لينكس واقرأ الفصل الخاص بإدارة الذاكرة.

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

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

تطوير نواة Linux بقلم روبرت لوف (الفصل 12، الصفحة 244 في الطبعة الثالثة) يجيب على هذا الأمر بوضوح شديد.

نعم، الذاكرة المتجاورة فعليًا ليست مطلوبة في كثير من الحالات.السبب الرئيسي لاستخدام kmalloc أكثر من vmalloc في kernel هو الأداء.يشرح الكتاب أنه عندما يتم تخصيص قطع كبيرة من الذاكرة باستخدام vmalloc، يتعين على kernel تعيين القطع (الصفحات) غير المتجاورة فعليًا في منطقة ذاكرة افتراضية واحدة متجاورة.نظرًا لأن الذاكرة متجاورة فعليًا وغير متجاورة فعليًا، يجب إضافة العديد من تعيينات العناوين الافتراضية إلى الفعلية إلى جدول الصفحات.وفي أسوأ الأحوال سيكون هناك (حجم المخزن المؤقت/حجم الصفحة) عدد التعيينات المضافة إلى جدول الصفحة.

يؤدي هذا أيضًا إلى زيادة الضغط على TLB (إدخالات ذاكرة التخزين المؤقت التي تخزن تعيينات العناوين الافتراضية إلى الفعلية الحديثة) عند الوصول إلى هذا المخزن المؤقت.هذا يمكن أن يؤدي إلى سحق.

ال kmalloc() & vmalloc() الوظائف هي واجهة بسيطة للحصول على ذاكرة kernel في أجزاء بحجم البايت.

  1. ال kmalloc() تضمن الوظيفة أن تكون الصفحات متجاورة فعليًا (ومتجاورة فعليًا).

  2. ال vmalloc() تعمل الوظيفة بطريقة مشابهة لـ kmalloc(), ، باستثناء أنه يخصص ذاكرة متجاورة فعليًا وليست بالضرورة متجاورة فعليًا.

ما هي مزايا وجود كتلة متجاورة من الذاكرة؟على وجه التحديد، لماذا أحتاج إلى كتلة فعلية متجاورة من الذاكرة في استدعاء النظام؟هل هناك أي سبب يمنعني من استخدام vmalloc فقط؟

من "أشعر أنني محظوظ" من Google vmalloc:

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

في نظام 32 بت، يقوم kmalloc() بإرجاع عنوان kernel المنطقي (على الرغم من أنه عنوان ظاهري) والذي يحتوي على تعيين مباشر (في الواقع مع إزاحة ثابتة) للعنوان الفعلي.يضمن هذا التعيين المباشر حصولنا على قطعة مادية متجاورة من ذاكرة الوصول العشوائي.مناسب لـ DMA حيث نعطي المؤشر الأولي فقط ونتوقع تعيينًا فعليًا متجاورًا بعد ذلك لعملياتنا.

يقوم vmalloc() بإرجاع عنوان kernel الظاهري والذي بدوره قد لا يكون له تعيين متجاور على ذاكرة الوصول العشوائي الفعلية.مفيد لتخصيص الذاكرة الكبيرة وفي الحالات التي لا نهتم فيها بأن الذاكرة المخصصة لعمليتنا مستمرة أيضًا في ذاكرة الوصول العشوائي الفعلية.

أحد الاختلافات الأخرى هو أن kmalloc سيُرجع العنوان المنطقي (وإلا فإنك تحدد GPF_HIGHMEM).يتم وضع العناوين المنطقية في "ذاكرة منخفضة" (في أول جيجابايت من الذاكرة الفعلية) ويتم تعيينها مباشرة إلى العناوين الفعلية (استخدم ماكرو __pa لتحويلها).تشير هذه الخاصية إلى أن الذاكرة المخصصة هي ذاكرة مستمرة.

ومن ناحية أخرى، فإن Vmalloc قادر على إرجاع العناوين الافتراضية من "الذاكرة العالية".لا يمكن تحويل هذه العناوين إلى عناوين فعلية بطريقة مباشرة (يجب عليك استخدام وظيفة Virt_to_page).

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