madvise(2)

الاسم
madvise - إعطاء نصيحة حول استخدام الذاكرة

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <sys/mman.h>

int madvise(size_t size;
            void addr[size], size_t size, int advice);

    متطلبات ماكروات اختبار الميزات لـ glibc (انظر feature_test_macros(7)):

madvise():
    بدءاً من glibc 2.19:
        _DEFAULT_SOURCE
    حتى glibc 2.19 متضمناً إياه:
        _BSD_SOURCE

الوصف
يُستخدم استدعاء النظام madvise() لإعطاء نصيحة أو توجيهات إلى النواة بشأن نطاق العناوين الذي يبدأ من العنوان addr وبحجم size. يعمل madvise() فقط على صفحات كاملة، لذا يجب أن يكون addr محاذياً للصفحة. تُقرب قيمة size لأقرب مضاعف لحجم الصفحة. في معظم الحالات، يكون الهدف من هذه النصيحة هو تحسين أداء النظام أو التطبيق.

في البداية، دعم استدعاء النظام مجموعة من قيم advice "التقليدية"، والتي تتوفر أيضًا في تطبيقات أخرى عديدة. (لاحظ، مع ذلك، أن madvise() غير محدد في POSIX.) لاحقًا، وُفر عدد من قيم advice الخاصة بلينكس.

  قيم النصيحة التقليدية
تسمح قيم advice المدرجة أدناه للتطبيق بإخبار النواة كيف يتوقع استخدام بعض مناطق الذاكرة المخططة أو المشتركة، حتى تتمكن النواة من اختيار تقنيات القراءة المسبقة والخبيئة المناسبة. لا تؤثر قيم advice هذه على دلالات التطبيق (باستثناء حالة MADV_DONTNEED)، ولكنها قد تؤثر على أدائه. جميع قيم advice المدرجة هنا لها نظائر في دالة posix_madvise(3) المحددة في POSIX، وللقيم نفس المعاني، باستثناء MADV_DONTNEED.

تُحدد النصيحة في وسيط advice، وهو أحد ما يلي:

MADV_NORMAL
    لا توجد معاملة خاصة. هذا هو المبدئي.

MADV_RANDOM
    توقع مراجع الصفحات بترتيب عشوائي. (وبالتالي، قد تكون القراءة المسبقة أقل فائدة من المعتاد.)

MADV_SEQUENTIAL
    توقع مراجع الصفحات بترتيب تسلسلي. (وبالتالي، يمكن قراءة الصفحات في النطاق المعطى مسبقاً بشكل مكثف، وقد تُحرر بعد وقت قصير من الوصول إليها.)

MADV_WILLNEED
    توقع الوصول في المستقبل القريب. (وبالتالي، قد يكون من الجيد قراءة بعض الصفحات مسبقاً.)

MADV_DONTNEED
    لا تتوقع الوصول في المستقبل القريب. (في الوقت الحالي، انتهى التطبيق من النطاق المعطى، لذا يمكن للنواة تحرير الموارد المرتبطة به.)

    بعد نجاح عملية MADV_DONTNEED، تتغير دلالات الوصول إلى الذاكرة في المنطقة المحددة: ستنجح عمليات الوصول اللاحقة للصفحات في النطاق، ولكنها ستؤدي إما إلى إعادة ملء محتويات الذاكرة من المحتويات الحديثة للملف المخطط الأساسي (بالنسبة لمخططات الملفات المشتركة، والمخططات المجهولة المشتركة، والتقنيات المستندة إلى shmem مثل مقاطع ذاكرة System V المشتركة) أو صفحات الملء بالصفر عند الطلب للمخططات الخاصة المجهولة.

    لاحظ أنه عند تطبيق MADV_DONTNEED على المخططات المشتركة، قد لا يؤدي ذلك إلى تحرير فوري للصفحات في النطاق. للنواة الحرية في تأخير تحرير الصفحات حتى لحظة مناسبة. ومع ذلك، سيُقلل حجم المجموعة المقيمة (RSS) للعملية المستدعِية على الفور.

    لا يمكن تطبيق MADV_DONTNEED على الصفحات المقفلة، أو صفحات VM_PFNMAP. (الصفحات المميزة بعلامة VM_PFNMAP الداخلية للنواة هي مناطق ذاكرة خاصة لا يُديرها نظام الذاكرة الوهمية الفرعي. تُنشأ مثل هذه الصفحات عادةً بواسطة برامج تشغيل الأجهزة التي تخطط الصفحات في مساحة المستخدم.)

    أُضيف دعم صفحات Huge TLB في لينكس 5.18. يجب أن تكون العناوين داخل مخطط مدعوم بصفحات Huge TLB محاذية لحجم صفحة Huge TLB الأساسي، ويُقرب حجم النطاق لأقرب مضاعف لحجم صفحة Huge TLB الأساسي.

  قيم النصيحة الخاصة بلينكس
قيم advice التالية الخاصة بلينكس ليس لها نظائر في posix_madvise(3) المحددة في POSIX، وقد يكون أو لا يكون لها نظائر في واجهة madvise() المتوفرة في تطبيقات أخرى. لاحظ أن بعض هذه العمليات تغير دلالات الوصول إلى الذاكرة.

MADV_REMOVE (منذ لينكس 2.6.16)
    تحرير نطاق معين من الصفحات ومخزنها الاحتياطي المرتبط بها. هذا يعادل ثقب فجوة في النطاق المقابل للمخزن الاحتياطي (انظر fallocate(2)). سترى عمليات الوصول اللاحقة في نطاق العناوين المحدد بيانات بقيمة صفر.

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

    في التطبيق الأولي، كان tmpfs(5) فقط يدعم MADV_REMOVE؛ ولكن منذ لينكس 3.5، فإن أي نظام ملفات يدعم وضع FALLOC_FL_PUNCH_HOLE في fallocate(2) يدعم أيضًا MADV_REMOVE. أنظمة الملفات التي لا تدعم MADV_REMOVE تفشل مع الخطأ EOPNOTSUPP.

    أُضيف دعم نظام ملفات Huge TLB في لينكس 4.3.

MADV_DONTFORK (منذ لينكس 2.6.16)
    عدم جعل الصفحات في هذا النطاق متاحة للابن بعد fork(2). هذا مفيد لمنع دلالات النسخ عند الكتابة من تغيير الموقع الفيزيائي للصفحة إذا كتب الأب فيها بعد fork(2). (مثل هذه التنقلات في الصفحات تسبب مشاكل للأجهزة التي تقوم بالوصول المباشر للذاكرة (DMA) في الصفحة.)

MADV_DOFORK (منذ لينكس 2.6.16)
    التراجع عن تأثير MADV_DONTFORK، واستعادة السلوك المبدئي، حيث يورث المخطط عبر fork(2).

MADV_HWPOISON (منذ لينكس 2.6.32)
    تسميم الصفحات في النطاق المحدد بواسطة addr و size والتعامل مع المراجع اللاحقة لتلك الصفحات كفساد في الذاكرة المادية. هذه العملية متاحة فقط للعمليات ذات الامتيازات (CAP_SYS_ADMIN). قد تؤدي هذه العملية إلى استلام العملية المستدعِية لإشارة SIGBUS وإلغاء تخطيط الصفحة.

    هذه الميزة مخصصة لاختبار كود معالجة أخطاء الذاكرة؛ وهي متاحة فقط إذا ضبطت النواة بـ CONFIG_MEMORY_FAILURE.

MADV_MERGEABLE (منذ لينكس 2.6.32)
    تمكين دمج الصفحات المتماثلة في النواة (KSM) للصفحات في النطاق المحدد بواسطة addr و size. تمسح النواة بانتظام مناطق ذاكرة المستخدم التي عُلمت كقابلة للدمج، بحثاً عن صفحات ذات محتوى متطابق. تُستبدل هذه بصفحة واحدة محمية ضد الكتابة (تُنسخ آلياً إذا أرادت عملية لاحقًا تحديث محتوى الصفحة). يدمج KSM الصفحات الخاصة المجهولة فقط (انظر mmap(2)).

    ميزة KSM مخصصة للتطبيقات التي تنشئ نسخاً عديدة من نفس البيانات (على سبيل المثال، أنظمة المحاكاة الوهمية مثل KVM). يمكن أن تستهلك الكثير من قوة المعالجة؛ استخدمها بحذر. انظر ملف مصدر نواة لينكس Documentation/admin-guide/mm/ksm.rst لمزيد من التفاصيل.

    عمليتا MADV_MERGEABLE و MADV_UNMERGEABLE متاحتان فقط إذا ضبطت النواة بـ CONFIG_KSM.

MADV_UNMERGEABLE (منذ لينكس 2.6.32)
    التراجع عن تأثير عملية MADV_MERGEABLE سابقة على نطاق العناوين المحدد؛ يقوم KSM بإلغاء دمج أي صفحات كان قد دمجها في نطاق العناوين المحدد بواسطة addr و size.

MADV_SOFT_OFFLINE (منذ لينكس 2.6.33)
    إخراج الصفحات في النطاق المحدد بواسطة addr و size من الخدمة بشكل ناعم. تُحفظ ذاكرة كل صفحة في النطاق المحدد (أي عند الوصول التالي، سيظهر المحتوى نفسه، ولكن في إطار صفحة فيزيائي جديد)، وتُخرج الصفحة الأصلية من الخدمة (أي لم تعد مستخدمة، وتُسحب من إدارة الذاكرة العادية). تأثير عملية MADV_SOFT_OFFLINE غير مرئي (أي لا يغير دلالات) العملية المستدعِية.

    هذه الميزة مخصصة لاختبار كود معالجة أخطاء الذاكرة؛ وهي متاحة فقط إذا ضبطت النواة بـ CONFIG_MEMORY_FAILURE.

MADV_HUGEPAGE (منذ لينكس 2.6.38)
    تمكين الصفحات الضخمة الشفافة (THP) للصفحات في النطاق المحدد بواسطة addr و size. ستمسح النواة بانتظام المناطق المميزة كمرشحة للصفحات الضخمة لاستبدالها بصفحات ضخمة. ستخصص النواة أيضًا صفحات ضخمة مباشرةً عندما تكون المنطقة محاذية بشكل طبيعي لحجم الصفحة الضخمة (انظر posix_memalign(2)).

    تهدف هذه الميزة بشكل رئيس إلى التطبيقات التي تستخدم مخططات كبيرة للبيانات وتصل إلى مناطق واسعة من تلك الذاكرة في وقت واحد (مثل أنظمة المحاكاة الوهمية مثل QEMU). يمكنها بسهولة تامة إهدار الذاكرة (على سبيل المثال، مخطط بحجم 2 ميجابايت لا يصل إلا إلى بايت واحد سيؤدي إلى 2 ميجابايت من الذاكرة المحجوزة بدلاً من صفحة واحدة بحجم 4 كيلوبايت). انظر ملف مصدر نواة لينكس Documentation/admin-guide/mm/transhuge.rst لمزيد من التفاصيل.

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

    منذ لينكس 5.4، يعمل المسح الآلي للمناطق المؤهلة والاستبدال بصفحات ضخمة مع الصفحات الخاصة المجهولة (انظر mmap(2))، وصفحات shmem، والصفحات المدعومة بالملفات. لجميع أنواع الذاكرة، قد تُستبدل الذاكرة بصفحات ضخمة فقط عند حدود محاذية للصفحة الضخمة. بالنسبة للذاكرة المخططة بالملفات —بما في ذلك tmpfs (انظر tmpfs(2))— يجب أن يكون المخطط أيضًا محاذياً بشكل طبيعي للصفحة الضخمة داخل الملف. بالإضافة إلى ذلك، بالنسبة للذاكرة المدعومة بالملفات وغير التابعة لـ tmpfs، يجب ألا يكون الملف مفتوحاً للكتابة ويجب أن يكون المخطط قابلاً للتنفيذ.

    يجب ألا تُعلم VMA بـ VM_NOHUGEPAGE أو VM_HUGETLB أو VM_IO أو VM_DONTEXPAND أو VM_MIXEDMAP أو VM_PFNMAP، كما لا يمكن أن تكون ذاكرة مكدس أو مدعومة بجهاز مفعل بـ DAX (ما لم يُوصل جهاز DAX كذاكرة رام للنظام). يمكن أن يكون للعملية PR_SET_THP_DISABLE مضبوطاً فقط إذا كان PR_THP_DISABLE_EXCEPT_ADVISED مضبوطاً (انظر prctl(2)).

    عمليات MADV_HUGEPAGE و MADV_NOHUGEPAGE و MADV_COLLAPSE متاحة فقط إذا ضبطت النواة بـ CONFIG_TRANSPARENT_HUGEPAGE، وذاكرة الملف/shmem مدعومة فقط إذا ضبطت النواة بـ CONFIG_READ_ONLY_THP_FOR_FS.

MADV_NOHUGEPAGE (منذ لينكس 2.6.38)
    يضمن أن الذاكرة في نطاق العناوين المحدد بواسطة addr و size لن تكون مدعومة بصفحات ضخمة شفافة.

MADV_COLLAPSE (منذ لينكس 6.1)
    إجراء طي متزامن بأقصى جهد للصفحات الأصلية المخططة بواسطة نطاق الذاكرة إلى صفحات ضخمة شفافة (THPs). يعمل MADV_COLLAPSE على الحالة الحالية لذاكرة العملية المستدعِية ولا يجري أي تغييرات دائمة أو ضمانات حول كيفية تخطيط الصفحات أو بنائها أو تعطلها في المستقبل.

    يدعم MADV_COLLAPSE الصفحات الخاصة المجهولة (انظر mmap(2))، وصفحات shmem، والصفحات المدعومة بالملفات. انظر MADV_HUGEPAGE للحصول على معلومات عامة حول متطلبات الذاكرة لـ THP. إذا كان النطاق المقدم يمتد عبر عدة VMAs، فإن دلالات الطي فوق كل VMA مستقلة عن الأخرى. إذا فشل طي منطقة معينة محاذية/بجم صفحة ضخمة، فقد تستمر العملية في محاولة طي بقية الذاكرة المحددة. سيقوم MADV_COLLAPSE آلياً بتقييد النطاق المقدم ليكون محاذياً للصفحة الضخمة.

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

    MADV_COLLAPSE مستقل عن أي إعداد لـ sysfs (انظر sysfs(5)) تحت /sys/kernel/mm/transparent_hugepage، سواء من حيث تحديد أهلية THP أو دلالات التخصيص. انظر ملف مصدر نواة لينكس Documentation/admin-guide/mm/transhuge.rst لمزيد من المعلومات. يتجاهل MADV_COLLAPSE أيضًا وصل tmpfs بـ huge= عند العمل على ملفات tmpfs. قد يدخل تخصيص الصفحة الضخمة الجديدة في الاسترداد المباشر و/أو الضغط، بغض النظر عن علامات VMA (رغم أنه لا يزال يُحترم VM_NOHUGEPAGE).

    عندما يحتوي النظام على عدة عُقد NUMA، ستُخصص الصفحة الضخمة من العقدة التي توفر أكبر عدد من الصفحات الأصلية.

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

MADV_DONTDUMP (منذ لينكس 3.4)
    استبعاد الصفحات في النطاق المحدد بواسطة addr و size من تفريغ الذاكرة (core dump). هذا مفيد في التطبيقات التي تحتوي على مناطق كبيرة من الذاكرة المعروف أنها غير مفيدة في تفريغ الذاكرة. يكون لتأثير MADV_DONTDUMP الأسبقية على قناع البتات الذي يُضبط عبر ملف /proc/pid/coredump_filter (انظر core(5)).

MADV_DODUMP (منذ لينكس 3.4)
    التراجع عن تأثير MADV_DONTDUMP سابقة.

MADV_FREE (منذ لينكس 4.5)
    لم يعد التطبيق يتطلب الصفحات في النطاق المحدد بواسطة addr و size. وبالتالي يمكن للنواة تحرير هذه الصفحات، ولكن قد يتأخر التحرير حتى يحدث ضغط على الذاكرة. لكل صفحة عُلمت لتُحرر ولكن لم تُحرر بعد، ستُلغى عملية التحرير إذا كتب المستدعِي في الصفحة. بعد نجاح عملية MADV_FREE، ستُفقد أي بيانات قديمة (أي الصفحات المتسخة وغير المكتوبة) عندما تحرر النواة الصفحات. ومع ذلك، ستنجح عمليات الكتابة اللاحقة للصفحات في النطاق ولن تتمكن النواة حينها من تحرير تلك الصفحات المتسخة، بحيث يمكن للمستدعِي دائماً رؤية البيانات المكتوبة للتو. إذا لم تكن هناك كتابة لاحقة، يمكن للنواة تحرير الصفحات في أي وقت. بمجرد تحرير الصفحات في النطاق، سيرى المستدعِي صفحات ملء بالصفر عند الطلب عند مراجع الصفحات اللاحقة.

    يمكن تطبيق العملية MADV_FREE فقط على الصفحات المجهولة الخاصة (انظر mmap(2)). قبل لينكس 4.12، عند تحرير الصفحات في نظام لا يحتوي على مساحة تبديل (swapless)، كانت الصفحات في النطاق المعطى تُحرر فوراً، بغض النظر عن ضغط الذاكرة.

MADV_WIPEONFORK (منذ لينكس 4.14)
    تقديم ذاكرة مملوءة بالأصفار للعملية الابن في هذا النطاق بعد fork(2). هذا مفيد في الخوادم التي تعتمد على التفريع لضمان عدم تسليم البيانات الحساسة الخاصة بكل عملية (مثل بذور PRNG، والأسرار التشفيرية، وما إلى ذلك) إلى العمليات الأبناء.

    يمكن تطبيق عملية MADV_WIPEONFORK فقط على الصفحات الخاصة المجهولة (انظر mmap(2)).

    داخل الابن الذي أنشئ بواسطة fork(2)، يظل إعداد MADV_WIPEONFORK قائماً على نطاق العناوين المحدد. يُمسح هذا الإعداد أثناء execve(2).

MADV_KEEPONFORK (منذ لينكس 4.14)
    التراجع عن تأثير MADV_WIPEONFORK سابقة.

MADV_COLD (منذ لينكس 5.4)
    إلغاء تنشيط نطاق معين من الصفحات. سيجعل هذا الصفحات هدفاً مرجحاً أكثر للاسترداد في حال حدوث ضغط على الذاكرة. هذه عملية غير تدميرية. قد تُتجاهل النصيحة لبعض الصفحات في النطاق عندما لا تكون قابلة للتطبيق.

MADV_PAGEOUT (منذ لينكس 5.4)
    استرداد نطاق معين من الصفحات. يتم ذلك لتحرير الذاكرة التي تشغلها هذه الصفحات. إذا كانت الصفحة مجهولة، فسيتم ترحيلها إلى مساحة التبادل. إذا كانت الصفحة مدعومة بملف ومتسخة، فسيتم كتابتها مرة أخرى إلى التخزين الاحتياطي. قد تُتجاهل النصيحة لبعض الصفحات في النطاق عندما لا تكون قابلة للتطبيق.

MADV_POPULATE_READ (منذ لينكس 5.14)
    ملء جداول الصفحات كقابلة للقراءة، مع إحضار جميع الصفحات في النطاق تماماً كما لو كان يتم القراءة يدوياً من كل صفحة؛ ومع ذلك، تجنب الوصول الفعلي للذاكرة الذي كان سيُجرى بعد معالجة الخطأ.

    على عكس MAP_POPULATE، لا يخفي MADV_POPULATE_READ الأخطاء، ويمكن تطبيقه على (أجزاء من) المخططات الموجودة وسيقوم دائماً بملء جداول الصفحات كقابلة للقراءة. إحدى حالات الاستخدام هي الإحضار المسبق لمخطط ملف، وقراءة كل محتوى الملف من القرص؛ ومع ذلك، لن تُلوث الصفحات وبالتالي لن يتعين كتابتها مرة أخرى على القرص عند إخلاء الصفحات من الذاكرة.

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

    إذا نجح MADV_POPULATE_READ، فقد ملئت جميع جداول الصفحات كقابلة للقراءة مرة واحدة. إذا فشل MADV_POPULATE_READ، فقد تكون بعض جداول الصفحات قد ملئت.

    لا يمكن تطبيق MADV_POPULATE_READ على المخططات التي لا تملك أذونات قراءة والمخططات الخاصة، على سبيل المثال، المخططات المميزة بعلامات داخلية للنواة مثل VM_PFNMAP أو VM_IO، أو مناطق الذاكرة السرية المنشأة باستخدام memfd_secret(2).

    لاحظ أنه مع MADV_POPULATE_READ، يمكن قتل العملية في أي لحظة عندما ينفد النظام من الذاكرة.

MADV_POPULATE_WRITE (منذ لينكس 5.14)
    ملء جداول الصفحات كقابلة للكتابة، مع إحضار جميع الصفحات في النطاق تماماً كما لو كان يتم الكتابة يدوياً في كل صفحة؛ ومع ذلك، تجنب الوصول الفعلي للذاكرة الذي كان سيُجرى بعد معالجة الخطأ.

    على عكس MAP_POPULATE، لا يخفي MADV_POPULATE_WRITE الأخطاء، ويمكن تطبيقه على (أجزاء من) المخططات الموجودة وسيقوم دائماً بملء جداول الصفحات كقابلة للكتابة. إحدى حالات الاستخدام هي التخصيص المسبق للذاكرة، كاسراً أي نسخ عند الكتابة (CoW).

    اعتماداً على المخطط الأساسي، التخصيص المسبق للذاكرة أو قراءة الملف الأساسي؛ ستقوم الملفات التي بها فجوات بتخصيص كتل مسبقاً. إذا فشل الملء، لا تُولد إشارة SIGBUS؛ بدلاً من ذلك، يُرجع خطأ.

    إذا نجحت MADV_POPULATE_WRITE، فتكون جميع جداول الصفحات قد وُزعت (أُخطئت مسبقًا) كقابلة للكتابة لمرة واحدة. إذا فشلت MADV_POPULATE_WRITE، فقد يكون قد وُزع بعض جداول الصفحات.

    لا يمكن تطبيق MADV_POPULATE_WRITE على التعيينات التي لا تملك أذونات كتابة والتعيينات الخاصة، على سبيل المثال، التعيينات المعلمة بأعلام النواة الداخلية مثل VM_PFNMAP أو VM_IO، أو مناطق الذاكرة السرية التي أُنشئت باستخدام memfd_secret(2).

    لاحظ أنه مع MADV_POPULATE_WRITE، يمكن قتل العملية في أي لحظة عندما ينفد نظام الذاكرة.

MADV_GUARD_INSTALL (منذ لينكس 6.13)
    ثبّت منطقة حماية خفيفة في النطاق المحدد بواسطة addr وsize، مما يتسبب في أن تؤدي أي قراءة أو كتابة في النطاق إلى رفع إشارة SIGSEGV.

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

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

    يجب ألا يكون التعيين مغلّقاً بـ mlock، أو يعيّن نطاقات hugetlb، ولا يحتوي على تعيينات خاصة. على سبيل المثال، التعيينات المعلمة بأعلام النواة الداخلية مثل VM_PFNMAP أو VM_IO، أو مناطق الذاكرة السرية المنشأة باستخدام memfd_secret(2).

    يُرجع الخطأ EINVAL إذا أُجريت محاولة على أي نوع آخر من التعييات.

    هذه العملية أكثر كفاءة من تعيين منطقة جديدة من الذاكرة بـ PROT_NONE، لأنها لا تتطلب إنشاء تعيينات جديدة. بدلاً من ذلك، يتم ببساطة التلاعب بجداول الصفحات لتعيين موجود لإنشاء السلوك المطلوب. ولا تُستخدم ذاكرة إضافية.

    تظل مناطق الحماية الخفيفة عند التفريع fork (باستثناء أي أجزاء طُبقت عليها MADV_WIPEONFORK)، ولا تُزال بواسطة MADV_DONTNEED أو MADV_FREE أو MADV_PAGEOUT أو MADV_COLD.

    ستفشل محاولة إجراء mlock(2) على مناطق الحماية الخفيفة، وكذلك ستفشل MADV_POPULATE_READ أو MADV_POPULATE_WRITE.

    إذا تغيرت سمات التعيين، أو قُسم أو أُلغي تعيينه جزئياً، تظل أي مناطق حماية موجودة في مكانها (إلا إذا أُلغي تعيينها).

    إذا نُقل تعيين باستخدام mremap(2)، فستُنقل مناطق الحماية الخفيفة معه.

    تُزال مناطق الحماية الخفيفة عند إلغاء التعيين، أو عند إنهاء العملية، أو عند تطبيق عملية MADV_GUARD_REMOVE عليها.

MADV_GUARD_REMOVE (منذ لينكس 6.13)
    أزل أي مناطق حماية خفيفة موجودة في النطاق المحدد بواسطة addr وsize.

    تُترك جميع التعيينات في النطاق بخلاف مناطق الحماية الخفيفة في مكانها. هذه العملية مدعومة في تلك التعيينات المسموح بها بواسطة MADV_GUARD_INSTALL بالإضافة إلى التعيينات المغلّقة بـ mlock()، مع إرجاع خطأ EINVAL في الحالات الأخرى.

    عند إزالة مناطق الحماية الخفيفة، فإنها تعمل كمناطق فارغة من التعيين الحاوي. لذلك، تصبح التعيينات الخاصة المجهولة صفحات تُملأ بالصفر عند الطلب، وتُعاد تعبئة التعيينات المدعومة بملفات بمحتويات الذاكرة من المحتويات المحدثة للملف المنيّن الأساسي.

    إذا واجهت العملية أي صفحات ضخمة شفافة، فستُترك في مكانها.

قيمة الإرجاع
عند النجاح، يرجع madvise() صفراً. عند حدوث خطأ، يرجع -1 ويُضبط errno للإشارة إلى الخطأ.

الأخطاء

EACCES
    advice هو MADV_REMOVE، لكن نطاق العنوان المحدد ليس تعييناً مشتركاً قابلاً للكتابة.

EAGAIN
    مورد للنواة غير متاح مؤقتاً.

EBADF
    التعيين موجود، لكن المنطقة تعيّن شيئاً ليس ملفاً.

EBUSY
    (لأجل MADV_COLLAPSE) لم يمكن تحميل الصفحة الضخمة إلى cgroup: تم تجاوز حد cgroup.

EBUSY
    (لأجل MADV_SOFT_OFFLINE) لم يمكن جعل أي صفحات ضمن نطاق العنوان المحدد خارج الخدمة (offline). قد يحدث هذا إذا كانت الصفحة قيد الاستخدام حالياً أو مغلقة.

EFAULT
    advice هو MADV_POPULATE_READ أو MADV_POPULATE_WRITE، وفشلت تعبئة (prefaulting) جداول الصفحات لأن SIGBUS كانت ستتولد عند الوصول الفعلي للذاكرة والسبب ليس صفحة مسمومة بالأجهزة (الصفحات المسمومة بالأجهزة يمكن، على سبيل المثال، إنشاؤها باستخدام العلم MADV_HWPOISON الموصوف في مكان آخر في هذه الصفحة).

EINVAL
    addr ليس محاذياً للصفحة أو size سالب.

EINVAL
    advice غير صالح.

EINVAL
    advice هو MADV_COLD أو MADV_PAGEOUT ونطاق العنوان المحدد يتضمن صفحات مغلقة، أو Huge TLB، أو صفحات VM_PFNMAP.

EINVAL
    advice هو MADV_DONTNEED أو MADV_REMOVE ونطاق العنوان المحدد يتضمن صفحات مغلقة، أو Huge TLB، أو صفحات VM_PFNMAP.

EINVAL
    advice هو MADV_MERGEABLE أو MADV_UNMERGEABLE، لكن النواة لم تُضبط بـ CONFIG_KSM.

EINVAL
    advice هو MADV_FREE أو MADV_WIPEONFORK لكن نطاق العنوان المحدد يتضمن نطاقات ملفات، أو Huge TLB، أو MAP_SHARED، أو VM_PFNMAP.

EINVAL
    advice هو MADV_POPULATE_READ أو MADV_POPULATE_WRITE، لكن نطاق العنوان المحدد يتضمن نطاقات بأذونات غير كافية أو تعييات خاصة، على سبيل المثال، التعيينات المعلمة بأعلام النواة الداخلية مثل VM_IO أو VM_PFNMAP، أو مناطق الذاكرة السرية المنشأة باستخدام memfd_secret(2).

EINVAL
    advice هو MADV_GUARD_INSTALL أو MADV_GUARD_REMOVE، لكن نطاق العنوان المحدد يحتوي على تعيين غير مدعوم.

EIO (لأجل MADV_WILLNEED) التصفير في هذه المنطقة سيتجاوز الحد الأقصى لحجم الطقم المقيم (resident set size) للعملية.

ENOMEM
    (لأجل MADV_WILLNEED) لا توجد ذاكرة كافية: فشل التصفير.

ENOMEM
    (لأجل MADV_COLLAPSE) لا توجد ذاكرة كافية: لم يمكن تخصيص صفحة ضخمة.

ENOMEM
    العناوين في النطاق المحدد غير معينة حالياً، أو تقع خارج فضاء عناوين العملية.

ENOMEM
    advice هو MADV_POPULATE_READ أو MADV_POPULATE_WRITE، وفشلت تعبئة (prefaulting) جداول الصفحات بسبب عدم كفاية الذاكرة.

EPERM
    advice هو MADV_HWPOISON، لكن المستدعي لا يملك صلاحية CAP_SYS_ADMIN.

EHWPOISON
    advice هو MADV_POPULATE_READ أو MADV_POPULATE_WRITE، وفشلت تعبئة (prefaulting) جداول الصفحات بسبب مواجهة صفحة مسمومة بالأجهزة (الصفحات المسمومة بالأجهزة يمكن، على سبيل المثال، إنشاؤها باستخدام العلم MADV_HWPOISON الموصوف في مكان آخر في هذه الصفحة).

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

تصف مواصفة POSIX.1-2001 استدعاء posix_madvise(3) مع الثوابت POSIX_MADV_NORMAL وPOSIX_MADV_RANDOM وPOSIX_MADV_SEQUENTIAL وPOSIX_MADV_WILLNEED وPOSIX_MADV_DONTNEED وما إلى ذلك، بسلوك قريب من الأعلام المسماة بشكل مشابه والمدرجة أعلاه.

  لينكس
يتطلب تطبيق لينكس أن يكون العنوان addr محاذياً للصفحة، ويسمح بأن يكون size صفراً. إذا كان هناك بعض الأجزاء من نطاق العنوان المحدد غير معينة، فإن نسخة لينكس من madvise() تتجاهلها وتطبق الاستدعاء على الباقي (لكنها ترجع ENOMEM من استدعاء النظام، كما يجب).

سيُرجع madvise(0, 0, advice) صفراً إذا وفقط إذا كان advice مدعوماً من قبل النواة ويمكن الاعتماد عليه لاستقصاء الدعم.

المعايير
لا يوجد.

التاريخ
ظهر لأول مرة في 4.4BSD.

منذ لينكس 3.18، أصبح دعم استدعاء النظام هذا اختيارياً، اعتماداً على ضبط خيار الإعداد CONFIG_ADVISE_SYSCALLS.

انظر أيضًا
getrlimit(2), memfd_secret(2), mincore(2), mmap(2), mprotect(2), msync(2), munmap(2), prctl(2), process_madvise(2), posix_madvise(3), core(5)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.