نگاشت حافظه os.mmap
صفحههای حافظه با دسترسی خواندن، نوشتن و اجرا: نگاشت، تغییر دسترسی و آزادسازی.
واردسازی سیستم عامل.نگاشت حافظه
نام آرگومانها شناسهی خود کد است و معادل فارسی ندارد؛ گونهها، کلیدواژهها و نام بستهها با معادل فارسی نوشته میشوند.
تخصیص معمولی (حافظه.تخصیص) حافظهای میدهد که میتوانید بخوانید و بنویسید. این بسته صفحههای کامل را مستقیم از سیستم عامل میدهد و اجازه میدهد انتخاب کنید برنامه با آنها چه کاری بکند: دسترسی خواندن، دسترسی نوشتن و دسترسی اجرا که با | ترکیب میشوند. تخصیص صفحههای صفرشده نگاشت میکند، تغییر دسترسی دسترسی را عوض میکند (mprotect) و آزادسازی آنها را برمیدارد. برای صفحهی نگهبان، برای دادهی فقطخواندنی که نباید اتفاقی عوض شود و برای بارگذاری کد ماشین به کار میآید: بایتها را وقتی صفحه نوشتنی است بنویسید، آن را روی خواندن و اجرا ببرید و با os.dl صدایش بزنید.
سیستم اندازه را تا صفحهی کامل بالا میبرد؛ اندازه صفحه اندازهی صفحه را میگوید (معمولاً ۴۰۹۶، روی تراشههای اپل ۱۶۳۸۴). بسته روی لینوکس، مک و بیاسدیها کار میکند. روی ویندوز پشتیبانی می شود نادرست است و تخصیص پوچ برمیگرداند.
اشتباههای رایج:
- خواستن نوشتن و اجرا با هم. چند سیستم نمیپذیرند (SELinux، هستههای سختشده، مک روی تراشهی اپل که پرچم ویژهی
MAP_JITهم میخواهد و این بسته نمیگذارد). در دو گام انجامش دهید: بادسترسی خواندن | دسترسی نوشتننگاشت کنید، پر کنید، بعدتغییر دسترسیرا رویدسترسی خواندن | دسترسی اجرابزنید. - دادن اندازهی متفاوت به
آزادسازییاتغییر دسترسینسبت بهتخصیص. همان اندازه را بدهید؛ دسترسی صفحههای کامل عوض میشود. - استفاده از حافظه بعد از
آزادسازییا نوشتن در صفحهای که حالا فقطخواندنی است. هر دو برنامه را همان لحظه میاندازند. - کد ماشین فقط برای یک خانوادهی پردازنده معتبر است. کد x86-64 روی رایانهی ARM اجرا نمیشود و بعضی سیستمهای ARM بعد از نوشتن کد باید حافظهی نهان دستورها را خالی کنند.
اجرای چند دستور ماشین
نمونهی زیر یک صفحه نگاشت میکند، هفت بایت کد x86-64 که دو آرگومان اولش را جمع میکند در آن مینویسد، صفحه را اجرایی میکند و صدایش میزند. فقط روی x86 ۶۴ بیتی اجرا میشود که نمونه با سلام معماری ایکس۶۴ میسنجد.
واردسازی سیستم عامل.بارگذاری کتابخانه
واردسازی سیستم عامل.نگاشت حافظه
تابع ریشه:
اگر وارونه سلام معماری ایکس۶۴ یا وارونه نگاشت حافظه.پشتیبانی می شود():
سرچاپ "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)
پایانجدولی که ناخواسته عوض نمیشود
صفحه را وقتی قابل نوشتن است پر کنید، بعد با تغییر دسترسی فقطخواندنیاش کنید. از آن پس نوشتن اشتباهی برنامه را همان لحظه متوقف میکند و جدول بیصدا خراب نمیشود، و خواندن همچنان کار میکند. وقتی داده باید عوض شود دوباره قابل نوشتنش کنید. نمونهی زیر این کار را با جدول مربعها نشان میدهد.
// زبان: فارسی
واردسازی سیستم عامل.نگاشت حافظه
تابع ریشه:
اگر وارونه نگاشت حافظه.پشتیبانی می شود():
سرچاپ "memory mapping is not available here"
برگشت
پایان
برگه := نگاشت حافظه.اندازه صفحه()
جدول := نگاشت حافظه.تخصیص(برگه، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
دیرکن _freed := نگاشت حافظه.آزادسازی(جدول، برگه)
خانه ها := جدول برگردان صحیح۳۲*
تکرار 16 در ا:
خانه ها[ا] = ا * ا
پایان
سرچاپ "filled:"، خانه ها[3]، خانه ها[15]
سرچاپ "read-only:"، نگاشت حافظه.تغییر دسترسی(جدول، برگه، نگاشت حافظه.دسترسی خواندن)
سرچاپ "still readable:"، خانه ها[4]
سرچاپ "writable again:"، نگاشت حافظه.تغییر دسترسی(جدول، برگه، نگاشت حافظه.دسترسی خواندن | نگاشت حافظه.دسترسی نوشتن)
خانه ها[4] = 99
سرچاپ "after the change:"، خانه ها[4]
پایانپایاها و متغیرها
بدون دسترسی PROT_NONE
پایا بدون دسترسی: صحیح۳۲ = 0واردسازی سیستم عامل.نگاشت حافظه
تابع ریشه:
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)
پایاندسترسی خواندن 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