کتابخانه‌ی استاندارد · سیستم و ابزار

نگاشت حافظه os.mmap

صفحه‌های حافظه با دسترسی خواندن، نوشتن و اجرا: نگاشت، تغییر دسترسی و آزادسازی.

واردسازی سیستم عامل.نگاشت حافظه

نام آرگومان‌ها شناسه‌ی خود کد است و معادل فارسی ندارد؛ گونه‌ها، کلیدواژه‌ها و نام بسته‌ها با معادل فارسی نوشته می‌شوند.

تخصیص معمولی (حافظه.تخصیص) حافظه‌ای می‌دهد که می‌توانید بخوانید و بنویسید. این بسته صفحه‌های کامل را مستقیم از سیستم عامل می‌دهد و اجازه می‌دهد انتخاب کنید برنامه با آن‌ها چه کاری بکند: دسترسی خواندن، دسترسی نوشتن و دسترسی اجرا که با | ترکیب می‌شوند. تخصیص صفحه‌های صفر‌شده نگاشت می‌کند، تغییر دسترسی دسترسی را عوض می‌کند (mprotect) و آزادسازی آن‌ها را برمی‌دارد. برای صفحه‌ی نگهبان، برای داده‌ی فقط‌خواندنی که نباید اتفاقی عوض شود و برای بارگذاری کد ماشین به کار می‌آید: بایت‌ها را وقتی صفحه نوشتنی است بنویسید، آن را روی خواندن و اجرا ببرید و با os.dl صدایش بزنید.

سیستم اندازه را تا صفحه‌ی کامل بالا می‌برد؛ اندازه صفحه اندازه‌ی صفحه را می‌گوید (معمولاً ۴۰۹۶، روی تراشه‌های اپل ۱۶۳۸۴). بسته روی لینوکس، مک و بی‌اس‌دی‌ها کار می‌کند. روی ویندوز پشتیبانی می شود نادرست است و تخصیص پوچ برمی‌گرداند.

اشتباه‌های رایج:

  • خواستن نوشتن و اجرا با هم. چند سیستم نمی‌پذیرند (SELinux، هسته‌های سخت‌شده، مک روی تراشه‌ی اپل که پرچم ویژه‌ی MAP_JIT هم می‌خواهد و این بسته نمی‌گذارد). در دو گام انجامش دهید: با دسترسی خواندن | دسترسی نوشتن نگاشت کنید، پر کنید، بعد تغییر دسترسی را روی دسترسی خواندن | دسترسی اجرا بزنید.
  • دادن اندازه‌ی متفاوت به آزادسازی یا تغییر دسترسی نسبت به تخصیص. همان اندازه را بدهید؛ دسترسی صفحه‌های کامل عوض می‌شود.
  • استفاده از حافظه بعد از آزادسازی یا نوشتن در صفحه‌ای که حالا فقط‌خواندنی است. هر دو برنامه را همان لحظه می‌اندازند.
  • کد ماشین فقط برای یک خانواده‌ی پردازنده معتبر است. کد x86-64 روی رایانه‌ی ARM اجرا نمی‌شود و بعضی سیستم‌های ARM بعد از نوشتن کد باید حافظه‌ی نهان دستورها را خالی کنند.

اجرای چند دستور ماشین

نمونه‌ی زیر یک صفحه نگاشت می‌کند، هفت بایت کد x86-64 که دو آرگومان اولش را جمع می‌کند در آن می‌نویسد، صفحه را اجرایی می‌کند و صدایش می‌زند. فقط روی x86 ۶۴ بیتی اجرا می‌شود که نمونه با سلام معماری ایکس۶۴ می‌سنجد.

os-mmap-guide-jit.salam
واردسازی سیستم عامل.بارگذاری کتابخانه
واردسازی سیستم عامل.نگاشت حافظه

تابع ریشه:
    اگر وارونه سلام معماری ایکس۶۴ یا وارونه نگاشت حافظه.پشتیبانی می شود():
        سرچاپ "this example needs 64 bit x86 and mmap"
        برگشت
    پایان
    page := نگاشت حافظه.اندازه صفحه()
    code := نگاشت حافظه.تخصیص(page، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
    bytes := code برگردان طبیعی۸*
    program := [0x48، 0x89، 0xf8، 0x48، 0x01، 0xf0، 0xc3]
    تکرار 7 در i:
        bytes[i] = program[i] برگردان طبیعی۸
    پایان
    نگاشت حافظه.تغییر دسترسی(code، page، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی اجرا)
    سرچاپ "40 + 2 ="، بارگذاری کتابخانه.فراخوان(code، [40 برگردان اندازه، 2])
    نگاشت حافظه.آزادسازی(code، page)
پایان
خروجی40 + 2 = 42

جدولی که ناخواسته عوض نمی‌شود

صفحه را وقتی قابل نوشتن است پر کنید، بعد با تغییر دسترسی فقط‌خواندنی‌اش کنید. از آن پس نوشتن اشتباهی برنامه را همان لحظه متوقف می‌کند و جدول بی‌صدا خراب نمی‌شود، و خواندن همچنان کار می‌کند. وقتی داده باید عوض شود دوباره قابل نوشتنش کنید. نمونه‌ی زیر این کار را با جدول مربع‌ها نشان می‌دهد.

os-mmap-guide-readonly.salam
// زبان: فارسی
واردسازی سیستم عامل.نگاشت حافظه

تابع ریشه:
    اگر وارونه نگاشت حافظه.پشتیبانی می شود():
        سرچاپ "memory mapping is not available here"
        برگشت
    پایان
    برگه := نگاشت حافظه.اندازه صفحه()
    جدول := نگاشت حافظه.تخصیص(برگه، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
    دیرکن _freed := نگاشت حافظه.آزادسازی(جدول، برگه)
    خانه ها := جدول برگردان صحیح۳۲*
    تکرار 16 در ا:
        خانه ها[ا] = ا * ا
    پایان
    سرچاپ "filled:"، خانه ها[3]، خانه ها[15]
    سرچاپ "read-only:"، نگاشت حافظه.تغییر دسترسی(جدول، برگه، نگاشت حافظه.دسترسی خواندن)
    سرچاپ "still readable:"، خانه ها[4]
    سرچاپ "writable again:"، نگاشت حافظه.تغییر دسترسی(جدول، برگه، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
    خانه ها[4] = 99
    سرچاپ "after the change:"، خانه ها[4]
پایان
خروجیfilled: 9 225 read-only: true still readable: 16 writable again: true after the change: 99

پایاها و متغیرها

بدون دسترسی PROT_NONE

پایا بدون دسترسی: صحیح۳۲ = 0
مقدار دسترسی: به صفحه‌ها نباید دست زد.
os-mmap-Alloc.salam
واردسازی سیستم عامل.نگاشت حافظه

تابع ریشه:
    page := نگاشت حافظه.اندازه صفحه()
    block := نگاشت حافظه.تخصیص(page، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
    اگر block برابر پوچ:
        سرچاپ "mapping failed"
        برگشت
    پایان
    bytes := block برگردان طبیعی۸*
    bytes[0] = 7 برگردان طبیعی۸
    bytes[page - 1] = 9 برگردان طبیعی۸
    سرچاپ bytes[0]، bytes[1]، bytes[page - 1]
    سرچاپ نگاشت حافظه.تغییر دسترسی(block، page، نگاشت حافظه.دسترسی خواندن)
    سرچاپ bytes[0]
    سرچاپ نگاشت حافظه.آزادسازی(block، page)
پایان
خروجی7 0 9 true 7 true

دسترسی خواندن PROT_READ

پایا دسترسی خواندن: صحیح۳۲ = 1
مقدار دسترسی: صفحه‌ها خوانده می‌شوند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

دسترسی نوشتن PROT_WRITE

پایا دسترسی نوشتن: صحیح۳۲ = 2
مقدار دسترسی: در صفحه‌ها نوشته می‌شود.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

دسترسی اجرا PROT_EXEC

پایا دسترسی اجرا: صحیح۳۲ = 4
مقدار دسترسی: صفحه‌ها به‌عنوان کد ماشین اجرا می‌شوند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

تابع‌ها

پشتیبانی می شود Supported

تابع پشتیبانی می شود(): منطقی
درست جایی که نگاشت حافظه کار می‌کند (هر سیستمی جز ویندوز).

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

اندازه صفحه PageSize

تابع اندازه صفحه(): صحیح
اندازه‌ی یک صفحه‌ی حافظه به بایت.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

تخصیص Alloc

تابع تخصیص(size: صحیح، prot: صحیح): تهی*
size بایت (تا صفحه‌ی کامل بالا رفته) حافظه‌ی خصوصی صفرشده را با دسترسی داده‌شده نگاشت می‌کند و نشانی‌اش را برمی‌گرداند، یا وقتی شکست بخورد، size مثبت نباشد و روی ویندوز پوچ.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

تغییر دسترسی Protect

تابع تغییر دسترسی(p: تهی*، size: صحیح، prot: صحیح): منطقی
دسترسی صفحه‌هایی را که size بایت از p را نگه می‌دارند عوض می‌کند؛ در موفقیت درست. p باید نشانی صفحه باشد، مثل آنچه تخصیص می‌دهد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam

آزادسازی Free

تابع آزادسازی(p: تهی*، size: صحیح): منطقی
صفحه‌ها را برمی‌دارد؛ در موفقیت درست. بعدش نباید از حافظه استفاده کرد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-mmap-Alloc.salam