- trixie-backports 4.31.0-1~bpo13+1
- testing 4.31.0-1
- unstable 4.31.0-1
| mremap(2) | System Calls Manual | mremap(2) |
الاسم¶
mremap - إعادة تعيين عنوان ذاكرة افتراضية
المكتبة¶
مكتبة سي المعيارية (libc، -lc)
موجز¶
#define _GNU_SOURCE /* انظر feature_test_macros(7) */ #include <sys/mman.h>
void *mremap(void old_address[.old_size], size_t old_size,
size_t new_size, int flags, ... /* void *new_address */);
الوصف¶
توسع mremap() (أو تقلص) تعيين ذاكرة موجود، مع إمكانية نقله في نفس الوقت (يُتحكم به بواسطة وسيط flags ومساحة العنوان الافتراضية المتاحة).
old_address هو العنوان القديم لكتلة الذاكرة الافتراضية التي تريد توسيعها (أو تقليصها). لاحظ أن old_address يجب أن يكون محاذيًا للصفحة. old_size هو الحجم القديم لكتلة الذاكرة الافتراضية. new_size هو الحجم المطلوب لكتلة الذاكرة الافتراضية بعد تغيير الحجم. يمكن توفير وسيطة خامسة اختيارية، new_address؛ انظر وصف MREMAP_FIXED أدناه.
إذا كانت قيمة old_size صفرًا، وكان old_address يشير إلى تعيين قابل للمشاركة (انظر وصف MAP_SHARED في mmap(2))، فستقوم mremap() بإنشاء تعيين جديد لنفس الصفحات. سيكون new_size هو حجم التعيين الجديد ويمكن تحديد موقع التعيين الجديد باستخدام new_address؛ انظر وصف MREMAP_FIXED أدناه. إذا طُلب تعيين جديد عبر هذه الطريقة، فيجب أيضًا تحديد العلم MREMAP_MAYMOVE.
قد يكون وسيط قناع البت flags 0، أو يتضمن الأعلام التالية:
- MREMAP_MAYMOVE
- بشكل مبدئي، إذا لم تكن هناك مساحة كافية لتوسيع تعيين في موقعه الحالي، تفشل mremap(). إذا حُدد هذا العلم، يُسمح للنواة بنقل التعيين إلى عنوان افتراضي جديد، إذا لزم الأمر. إذا نُقل التعيين، تصبح المؤشرات المطلقة إلى موقع التعيين القديم غير صالحة (يجب استخدام الإزاحات النسبية لعنوان بداية التعيين).
- MREMAP_FIXED (منذ Linux 2.3.31)
- يخدم هذا العلم غرضًا مشابهًا للعلم MAP_FIXED الخاص بـ mmap(2). إذا حُدد هذا العلم، تقبل mremap() وسيطًا خامسًا، void *new_address، والذي يحدد عنوانًا محاذيًا للصفحة يجب نقل التعيين إليه. يُلغى تعيين أي تعيين سابق في نطاق العنوان المحدد بواسطة new_address وnew_size.
- إذا حُدد MREMAP_FIXED، فيجب أيضًا تحديد MREMAP_MAYMOVE.
- MREMAP_DONTUNMAP (منذ Linux 5.7)
- هذا العلم، الذي يجب استخدامه بالتزامن مع MREMAP_MAYMOVE، يعيد تعيين تعيين إلى عنوان جديد لكنه لا يلغي تعيين التعيين في old_address.
- يمكن استخدام العلم MREMAP_DONTUNMAP فقط مع التعيينات الخاصة المجهولة (انظر وصف MAP_PRIVATE و MAP_ANONYMOUS في mmap(2)).
- بعد الإكمال، أي وصول إلى النطاق المحدد بواسطة old_address وold_size سيؤدي إلى خطأ صفحة. سيُعالج خطأ الصفحة بواسطة معالج userfaultfd(2) إذا كان العنوان في نطاق سُجل مسبقًا مع userfaultfd(2). بخلاف ذلك، تخصص النواة صفحة مملوءة بالأصفار لمعالجة الخطأ.
- يمكن استخدام العلم MREMAP_DONTUNMAP لنقل تعيين بشكل ذري مع ترك المصدر معينًا. انظر الملاحظات لبعض التطبيقات الممكنة لـ MREMAP_DONTUNMAP.
إذا كان مقطع الذاكرة المحدد بواسطة old_address و old_size مقفلاً (باستخدام mlock(2) أو ما شابه)، فسيُحافظ على هذا القفل عند تغيير حجم المقطع و/أو نقله. نتيجة لذلك، قد يتغير مقدار الذاكرة المقفلة بواسطة العملية.
قيمة الإرجاع¶
عند النجاح، ترجع mremap() مؤشرًا إلى منطقة الذاكرة الافتراضية الجديدة. عند الخطأ، تُرجع القيمة MAP_FAILED (أي، (void *) -1)، ويُعين errno للإشارة إلى الخطأ.
الأخطاء¶
- EAGAIN
- حاول المستدعي توسيع مقطع ذاكرة مقفل، لكن هذا لم يكن ممكنًا دون تجاوز حد المورد RLIMIT_MEMLOCK.
- EFAULT
- بعض العناوين في النطاق old_address إلى old_address+old_size هو عنوان ذاكرة افتراضية غير صالح لهذه العملية. يمكنك أيضًا الحصول على EFAULT حتى لو كانت هناك تعيينات تغطي مساحة العنوان الكاملة المطلوبة، لكن تلك التعيينات من أنواع مختلفة.
- EINVAL
- أُعطي وسيط غير صالح. الأسباب المحتملة هي:
- •
- old_address لم يكن محاذيًا للصفحة؛
- •
- حُدد قيمة غير MREMAP_MAYMOVE أو MREMAP_FIXED أو MREMAP_DONTUNMAP في flags؛
- •
- new_size كان صفرًا؛
- •
- new_size أو new_address كان غير صالح؛
- •
- نطاق العنوان الجديد المحدد بواسطة new_address و new_size تداخل مع نطاق العنوان القديم المحدد بواسطة old_address و old_size؛
- •
- حُدد MREMAP_FIXED أو MREMAP_DONTUNMAP دون تحديد MREMAP_MAYMOVE أيضًا؛
- •
- حُدد MREMAP_DONTUNMAP، لكن صفحة واحدة أو أكثر في النطاق المحدد بواسطة old_address و old_size لم تكن خاصة مجهولة؛
- •
- حُدد MREMAP_DONTUNMAP و old_size لم يكن مساويًا لـ new_size؛
- •
- old_size كان صفرًا و old_address لا يشير إلى تعيين قابل للمشاركة (لكن انظر الأخطاء)؛
- •
- old_size كان صفرًا ولم يُحدد العلم MREMAP_MAYMOVE.
- ENOMEM
- لم تكن ذاكرة كافية متاحة لإكمال العملية. الأسباب المحتملة هي:
- •
- لا يمكن توسيع منطقة الذاكرة في العنوان الافتراضي الحالي، والعلم MREMAP_MAYMOVE غير مضبوط في flags. أو، لا توجد ذاكرة (افتراضية) كافية متاحة.
- •
- اُستخدمت MREMAP_DONTUNMAP مما تسبب في إنشاء تعيين جديد يتجاوز الذاكرة (الافتراضية) المتاحة. أو، سيتجاوز الحد الأقصى لعدد التعيينات المسموح بها.
المعايير¶
لينكس.
التاريخ¶
قبل glibc 2.4، لم يكشف glibc عن تعريف MREMAP_FIXED، ولم يسمح النموذج الأولي لـ mremap() بالوسيطة new_address.
ملاحظات¶
تغير mremap() التعيين بين العناوين الافتراضية وصفحات الذاكرة. يمكن استخدام هذا لتنفيذ realloc(3) فعال جدًا.
في لينكس، تنقسم الذاكرة إلى صفحات. العملية لديها (واحد أو) عدة مقاطع ذاكرة افتراضية خطية. كل مقطع ذاكرة افتراضية لديه تعيين واحد أو أكثر لصفحات ذاكرة حقيقية (في جدول الصفحات). كل مقطع ذاكرة افتراضية لديه حمايته الخاصة (حقوق الوصول)، والتي قد تسبب انتهاكًا للتجزئة (SIGSEGV) إذا وُصل إلى الذاكرة بشكل غير صحيح (مثل، الكتابة إلى مقطع للقراءة فقط). الوصول إلى الذاكرة الافتراضية خارج المقاطع سيسبب أيضًا انتهاكًا للتجزئة.
إذا اُستخدمت mremap() لنقل أو توسيع منطقة مقفلة بـ mlock(2) أو ما يعادله، فستبذل استدعاء mremap() أقصى جهد لملء المنطقة الجديدة لكنها لن تفشل بـ ENOMEM إذا تعذر ملء المنطقة.
حالات استخدام MREMAP_DONTUNMAP¶
التطبيقات الممكنة لـ MREMAP_DONTUNMAP تشمل:
- •
- userfaultfd(2) غير التعاوني: يمكن للتطبيق سحب نطاق عنوان افتراضي باستخدام MREMAP_DONTUNMAP ثم استخدام معالج userfaultfd(2) للتعامل مع أخطاء الصفحة التي تحدث لاحقًا عندما تلمس خيوط أخرى في العملية صفحات في النطاق المسحوب.
- •
- جمع القمامة: يمكن استخدام MREMAP_DONTUNMAP بالتزامن مع userfaultfd(2) لتنفيذ خوارزميات جمع القمامة (مثل، في آلة جافا الافتراضية). يمكن أن يكون هذا التنفيذ أرخص (وأبسط) من تقنيات جمع القمامة التقليدية التي تتضمن وضع علامات على الصفحات بحماية PROT_NONE بالتزامن مع استخدام معالج SIGSEGV لالتقاط الوصول إلى تلك الصفحات.
العلل¶
قبل لينكس 4.14، إذا كان old_size صفرًا وكان التعيين المشار إليه بـ old_address تعيينًا خاصًا (انظر وصف MAP_PRIVATE في mmap(2))، أنشأت mremap() تعيينًا خاصًا جديدًا غير مرتبط بالتعيين الأصلي. كان هذا السلوك غير مقصود وربما غير متوقع في تطبيقات مساحة المستخدم (لأن هدف mremap() هو إنشاء تعيين جديد بناءً على التعيين الأصلي). منذ لينكس 4.14، تفشل mremap() مع الخطأ EINVAL في هذا السيناريو.
انظر أيضًا¶
brk(2), getpagesize(2), getrlimit(2), mlock(2), mmap(2), sbrk(2), malloc(3), realloc(3)
كتابك المدرسي المفضل عن أنظمة التشغيل لمزيد من المعلومات حول الذاكرة المقسمة إلى صفحات (مثل، Modern Operating Systems بقلم Andrew S. Tanenbaum، Inside Linux بقلم Randolph Bentson، The Design of the UNIX Operating System بقلم Maurice J. Bach)
ترجمة¶
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com> و #
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.
| 2 مايو 2024 | صفحات دليل لينكس 6.9.1 |