سؤال

أحاول معرفة كيفية إعادة تعيين الملفات المعينة للذاكرة على جهاز Mac (عندما أرغب في توسيع المساحة المتاحة).

أرى أصدقائنا في عالم Linux لديهم mremap لكن لا يمكنني العثور على أي وظيفة في الرؤوس على جهاز Mac الخاص بي. /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h لديه ما يلي:

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • لكن لا mremap

man mremap يؤكد مخاوفي.

أنا حاليا يجب أن munmap و mmmap إذا كنت أرغب في تغيير حجم الملف المعين ، والذي يتضمن إبطال جميع الصفحات المحملة. يجب أن تكون هناك طريقة أفضل. بالتاكيد؟

أحاول كتابة التعليمات البرمجية التي ستعمل على Mac OS X و Linux. يمكنني تسوية الماكرو لاستخدام أفضل وظيفة في كل حالة إذا كنت كان لكني أفضل القيام بذلك بشكل صحيح.

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

المحلول

يمكنك ftruncate الملف بحجم كبير (إنشاء ثقب) و MMAP كل ذلك. إذا كان الملف ثابتًا ، فإنني أوصي بملء الفتحة بمكالمات الكتابة بدلاً من الكتابة في التعيين ، وإلا فإن كتل الملف قد تكون مجزأة على القرص.

نصائح أخرى

إذا كنت بحاجة إلى تقليص الخريطة ، فقط munmap الجزء في النهاية تريد إزالته.

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

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

إذا كنت تتوسع في قطع كبيرة بما يكفي (على سبيل المثال ، 64 ميغابايت ، ولكن ذلك يعتمد على مدى سرعة نموه) ، فإن تكلفة إبطال الخريطة القديمة لا تذكر. كما هو الحال دائمًا ، المعيار قبل افتراض مشكلة.

ليس لدي أي خبرة في تعيين الذاكرة ، لكن يبدو أنه يمكنك تعيين نفس الملف مؤقتًا مرتين كوسيلة لتوسيع التعيين دون فقدان أي شيء.

int main() {
    int fd;
    char *fp, *fp2, *pen;

      /* create 1K file */
    fd = open( "mmap_data.txt", O_RDWR | O_CREAT, 0777 );
    lseek( fd, 1000, SEEK_SET );
    write( fd, "a", 1 );

      /* map and populate it */
    fp = mmap( NULL, 1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
    pen = memset( fp, 'x', 1000 );

      /* expand to 8K and establish overlapping mapping */
    lseek( fd, 8000, SEEK_SET );
    write( fd, "b", 1 );
    fp2 = mmap( NULL, 7000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );

      /* demonstrate that mappings alias */
    *fp = 'z';
    printf( "%c ", *fp2 );

      /* eliminate first mapping */
    munmap( fp, 1000 );

      /* populate second mapping */
    pen = memset( fp2+10, 'y', 7000 );

      /* wrap up */
    munmap( fp2, 7000 );
    close( fd );
    printf( "%d\n", errno );
}

الإخراج هو zxxxxxxxxxyyyyyy.....

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

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