ویرگول
ورودثبت نام
علی یوسفی
علی یوسفیادیولوژیست ( شنوایی شناس ) - توسعه دهنده اندروید
علی یوسفی
علی یوسفی
خواندن ۶ دقیقه·۱ ماه پیش

و چنین گفت سیلبرشاتس - فصل 9 - بخش 2

⭕ 9.1.3 فضای آدرس‌های منطقی در مقابل فضای آدرس‌های فیزیکی

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

وقتی آدرس‌ها در زمان کامپایل یا بارگذاری برنامه (binding) می‌شوند، آدرس‌های منطقی و فیزیکی یکسان هستند. اما زمانی که binding آدرس‌ها در زمان اجرا انجام می‌شود، آدرس‌های منطقی و فیزیکی متفاوت خواهند بود. در این حالت، ما معمولاً به آدرس منطقی، آدرس مجازی (virtual address) نیز می‌گوییم. در این متن، ما از اصطلاحات آدرس منطقی و آدرس مجازی به جای یکدیگر استفاده می‌کنیم.

مجموعه تمام آدرس‌های منطقی، فضای آدرس منطقی (logical address space) نام دارد. مجموعه تمامی آدرس‌های فیزیکی که با این آدرس‌های منطقی مرتبط هستند، فضای آدرس فیزیکی (physical address space) نامیده می‌شود. بنابراین، در حالت binding در زمان اجرا، فضای آدرس منطقی و فیزیکی متفاوت هستند.

در حالت binding در زمان اجرا ،mapping آدرس‌های مجازی به آدرس‌های فیزیکی توسط واحد مدیریت حافظه (Memory-Management Unit یا MMU) انجام می‌شود (تصویر 9.4).

ما می‌توانیم روش‌های مختلفی برای انجام این mapping انتخاب کنیم، همان‌طور که در بخش‌های 9.2 تا 9.3 بحث می‌شود.

فعلاً، این mapping را با یک طرح ساده از MMU نشان می‌دهیم که بر اساس base register است، که در بخش 9.1.1 توضیح داده شد و در اینجا (relocation register) نامیده میشود. مقدار موجود در relocation register به هر آدرس منطقی در زمانی که آدرس به حافظه فرستاده می‌شود، اضافه می‌شود (نگاه کنید به شکل 9.5).

برای مثال، اگر مقدار relocation register برابر با 14000 باشد، هر وقت پردازه تلاش کند به مکان 0 آدرس دهی کند، این آدرس به صورت دینامیک به مکان 14000 تغییر پیدا می‌کند؛ و اگر آدرسی مانند 346 باشد، این آدرس به مکان 14346، map می‌شود.

برنامه کاربر هرگز به آدرس‌های فیزیکی واقعی دسترسی ندارد. برنامه فقط می‌تواند پوینتری به مکان 346 بسازد، آن را در حافظه ذخیره کند، با آن عملیات انجام دهد، و با آدرس‌های دیگر مقایسه کند(برنامه اینطور فکر میکند که کل حافظه متعلق به اوست) ؛ (پردازه ها به شکل ناجوانمردانه ای دچار درون گرایی تحمیلی هستند 😔)

در یک جمله ، وظیفه MMU برقراری ارتباط بین آدرس های منطقی و فیزیکی است.

⭕ 9.1.4 بارگذاری پویا (Dynamic Loading)

در بحثی که تا اینجا داشتیم، لازم بود که کل برنامه و تمام داده‌های آن برای اجرای در حافظهٔ فیزیکی قرار داشته باشند. بنابراین، احتمال کمبود فضای حافظه همواره وجود داشت. برای به‌دست آوردن استفادهٔ بهتر از فضای حافظه، می‌توانیم از بارگذاری پویا استفاده کنیم.

در بارگذاری پویا، یک روال (routine) تا زمانی که فراخوانی نشود، بارگذاری نمی‌شود. همهٔ routine ها روی دیسک، در قالبی از برنامه که قابلیت جابه‌جایی دارد (relocatable load format) نگهداری می‌شوند.

برنامهٔ اصلی در حافظه بارگذاری می‌شود و اجرا می‌گردد. وقتی یک routine نیاز داشته باشد routine دیگری را فراخوانی کند، routine یی که فراخوانی را انجام می‌دهد ابتدا بررسی می‌کند که آیا routine مدنظرش بارگذاری شده است یا نه. اگر نشده باشد، relocatable linking loader فراخوانی می‌شود تا routine موردنظر را در حافظه بارگذاری کند و جدول‌های آدرس برنامه را به‌روزرسانی کند تا این تغییر در جدول آدرس اعمال شود. سپس کنترل روند به routine تازه بارگذاری‌شده منتقل می‌شود.

مزیت بارگذاری پویا این است که یک routine فقط زمانی بارگذاری می‌شود که واقعاً به آن نیاز باشد. این روش به‌ویژه وقتی مفید است که مقدار زیادی کد برای رسیدگی به حالت‌هایی که به‌ندرت رخ می‌دهند لازم باشد، مانند routine های خطا. در چنین وضعیتی، هرچند اندازهٔ کل برنامه ممکن است بزرگ باشد، بخشی که مورد استفاده قرارمیگیرد ممکن است خیلی کوچک‌تر باشد.

بارگذاری پویا به پشتیبانی ویژه‌ای از سوی سیستم‌عامل نیاز ندارد. این وظیفهٔ کاربران است که برنامه‌های خود را طوری طراحی کنند که از چنین روشی بهره ببرند. با این حال، سیستم‌عامل‌ها ممکن است با فراهم کردن روال‌های کتابخانه‌ای برای پیاده‌سازی بارگذاری پویا، به برنامه‌نویس کمک کنند.

داخل برنامه هامون وقتی که میایم یه کتابخونه رو import میکنیم ، عملا داریم از این مدل بارگزاری استفاده میکنیم


⭕ 9.1.5 پیوند پویا و کتابخانه‌های مشترک (Dynamic Linking and Shared Libraries)

کتابخانه‌های پیوند پویا (dynamically linked libraries یا DLLها) کتابخانه‌های سیستمی هستند که هنگام اجرای برنامه‌ها به آن‌ها پیوند داده می‌شوند (به شکل 9.3 مراجعه کنید). برخی سیستم‌عامل‌ها فقط پیوند ایستا (static linking) را پشتیبانی می‌کنند؛ در این حالت، کتابخانه‌های سیستم مانند هر ماژول شیء دیگری در نظر گرفته می‌شوند و توسط (loader) با فایل دودویی برنامه ترکیب می‌شوند.

در مقابل، پیوند پویا شبیه بارگذاری پویا است. با این تفاوت که در اینجا پیوند دادن، نه بارگذاری، تا زمان اجرا به تعویق می‌افتد. این ویژگی معمولاً برای کتابخانه‌های سیستمی، مانند کتابخانهٔ استاندارد زبان C، استفاده می‌شود. بدون این امکان، هر برنامه در یک سیستم باید یک نسخه از کتابخانهٔ زبان خود را (یا دست‌کم روال‌هایی را که برنامه به آن‌ها ارجاع می‌دهد) در فایل اجرایی خود داشته باشد. این الزام نه‌تنها اندازهٔ فایل اجرایی را افزایش می‌دهد، بلکه ممکن است باعث هدر رفتن حافظهٔ اصلی نیز شود.

مزیت دوم DLLها این است که این کتابخانه‌ها می‌توانند بین چندین پردازه به اشتراک گذاشته شوند، به‌طوری‌که فقط یک نمونه از DLL در حافظهٔ اصلی وجود داشته باشد به همین دلیل، DLLها همچنین با نام کتابخانه‌های مشترک (shared libraries) شناخته می‌شوند و به‌طور گسترده در سیستم‌های Windows و Linux استفاده می‌شوند.

وقتی برنامه‌ای به routine ارجاع می‌دهد که در یک کتابخانهٔ پویا قرار دارد، (loader) DLL را پیدا می‌کند و اگر لازم باشد آن را در حافظه بارگذاری می‌کند. سپس آدرس‌هایی را که به توابع موجود در کتابخانهٔ پویا ارجاع می‌دهند، با مکان حافظه‌ای که DLL در آن ذخیره شده است تنظیم می‌کند.

یک کتابخانه ممکن است با نسخهٔ جدیدی جایگزین شود و همهٔ برنامه‌هایی که به آن کتابخانه ارجاع می‌دهند، به‌طور خودکار از نسخهٔ جدید استفاده خواهند کرد. بدون پیوند پویا، همهٔ این برنامه‌ها باید دوباره پیوند داده شوند تا بتوانند به کتابخانهٔ جدید دسترسی پیدا کنند.

برای اینکه برنامه‌ها به‌اشتباه ، نسخه‌های جدید اما ناسازگار کتابخانه‌ها را اجرا نکنند، اطلاعات نسخه (version information) هم در برنامه و هم در کتابخانه گنجانده می‌شود. ممکن است بیش از یک نسخه از یک کتابخانه در حافظه بارگذاری شود، و هر برنامه از اطلاعات نسخهٔ خود برای تصمیم‌گیری دربارهٔ اینکه کدام نسخهٔ کتابخانه را استفاده کند بهره می‌گیرد.

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

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

ما این مفهوم را، و همچنین اینکه DLLها چگونه می‌توانند توسط چندین فرایند به اشتراک گذاشته شوند، هنگام بحث دربارهٔ صفحه‌بندی در بخش 9.3.4 بیشتر توضیح خواهیم داد.

برنامه نویسیهوش مصنوعی
۷
۰
علی یوسفی
علی یوسفی
ادیولوژیست ( شنوایی شناس ) - توسعه دهنده اندروید
شاید از این پست‌ها خوشتان بیاید