امیررضا ریاحی
امیررضا ریاحی
خواندن ۵ دقیقه·۳ سال پیش

نگاهی بر مدیریت حافظه توسط سیستم‌عامل - حافظه مجازی

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

swapping چیست؟

به دلایل متعددی، که بخشی از آن‌ها در پست‌های اخیر ذکر شده، هر دستورالعمل یا instruction که پردازنده نیاز دارد اجرا کند، حتما باید داخل حافظه اصلی کامپیوتر بارگذاری شده باشد. این یعنی پردازنده نمی‌تواند instruction هایی که داخل دیسک (مثلا حافظه HDD یا SSD) ذخیره شده‌اند را مستقیما اجرا کند. این مسئله یک مشکل خیلی بدیهی بوجود می‌آرود و آن عدم وجود حافظه کافی برای اجرا چندین پروسه همزمان است. همچنین در برخی موقعیت‌ها ممکن است پروسه‌هایی وجود داشته باشند، که هنوز تمام ( terminate) نشده‌اند اما فعلا به دلایلی غیرفعال هستند. مثلا منتظر رسیدن ورودی از سمت کاربر یا شبکه هستند یا هر چیز دیگری.

در این شرایط، سیستم‌عامل برای استفاده بهینه‌تر از حافظه اصلی، داده‌های این پروسه‌های غیرفعال را به دیسک یا swap space منتقل می‌کند (اصطلاحا swap out)، و از آن حافظه برای پروسه‌های فعالی که حافظه کافی ندارند استفاده می‌کند (اصطلاحا swap in).

پروسه P1 از حافظه اصلی خارج می‌شود و پروسه P2 جایگزین آن می‌شود
پروسه P1 از حافظه اصلی خارج می‌شود و پروسه P2 جایگزین آن می‌شود


حافظه مجازی یا virtual memory چیست؟

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

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

اندازه حافظه مجازی می‌تواند خیلی بیشتر از اندازه حافظه واقعی کامپیوتر باشد
اندازه حافظه مجازی می‌تواند خیلی بیشتر از اندازه حافظه واقعی کامپیوتر باشد


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

همچنین چیزی داریم به نام virtual address space که آدرس‌های ممکن و قابل استفاده برای هر برنامه خاص است. این فضای آدرس‌دهی، به این دلیل که سیستم‌عامل به طور پویا داده‌ها را از حافظه به دیسک منتقل می‌کند، می‌تواند بسیار بیشتر از مقدار اصلی حافظه کامپیوتر باشد. یعنی مثلا وقتی کل حافظه اصلی ۸ گیگابایت است، هر برنامه فضایی به وسعت ۴ گیگابایت دارد. در روش سنتی، اگر ۲ برنامه با فضای آدرس‌دهی ۴ گیگابایت اجرا کنیم، کل حافظه پر می‌شود. اما سیستم‌عامل‌های امروزی که از حافظه مجازی پشتیبانی می‌کنند می‌توانند تعداد زیادی برنامه را با فضای آدرس‌دهی خیلی بزرگ مدیریت کنند طوری که هیچ‌کدام به مشکل برنخورند. همان‌طور که در تصویر بالاتر نشان داده شده است، حافظه مجازی بزرگ‌تر است از حافظه اصلی (فیزیکی) و مقادیری از داده‌های روی حافظه مجازی، داخل دیسک یا همان backing store هستند.

به علاوه، از آنجایی که حافظه مجازی، نگاه برنامه به حافظه را به‌شدت انتزاعی‌تر و ساده‌تر می‌کند، سیستم‌عامل می‌تواند داده‌های یکسانی که چند برنامه به صورت اشتراک استفاده می‌کنند را در یک حافظه واحد نگه‌دارد. چیزی که مشابه آن را در paging هم دیدیم.

paging on demand

یکی از مرسوم‌ترین روش‌های استفاده شده در پیاده‌سازی حافظه مجازی، paging-on-demand است. وقتی یک برنامه اجرا می‌شود، احتمالا تمام آپشن‌های آن برنامه مورد نیاز نیست. پس لازم نیست که کل برنامه وارد حافظه شود. ابتدا سیستم‌عامل حافظه مجازی برنامه را تخصیص می‌دهد طوری که از نگاه خود برنامه، همه چیز در حافظه است. اما در واقعیت بخش‌هایی از برنامه در دیسک نشسته‌اند و هنوز وارد حافظه نشده‌اند. اجرا برنامه ادامه می‌یابد با حداقل page هایی از برنامه که نیاز دارند در حافظه باشند. هر وقت برنامه به بخشی از داده‌ها یا حافظه نیاز داشت که داخل page های بارگذاری شده در حافظه نبود، سیستم‌عامل موظف است سریعا این page را از دیسک به حافظه منتقل کند. اصطلاحا به این شرایط page fault گفته می‌شود. یعنی برنامه page ای را بخواهد که هنوز وارد حافظه مجازی نشده.

‌page هایی که هنوز وارد حافظه نشده‌اند، در page-table موجود هستند، اما با یک بیت، نشان داده می‌شود که این page در حافظه نیست.

همان‌طور که در تصویر نشان داده شده، از نگاه برنامه، تمامی داده‌ها روی حافظه هستند ( حافظه logical) اما در واقعیت این‌طور نیست. و در page-table مشخص است که کدام یک از این page ها آماده برای استفاده هستند یا نه.

هر وقت یک page-fault رخ می‌دهد، چند مرحله باید طی شود، تا page مورد نظر از دیسک به حافظه منتقل شود. این مراحل به‌طور مختصر در شکل زیر نمایش داده شده‌اند.

بعد از  اینکه page مورد نظر وارد حافظه شد، page-table تصحیح می‌شود
بعد از اینکه page مورد نظر وارد حافظه شد، page-table تصحیح می‌شود


از تصویر بالا واضح است که هزینه پردازشی هر page-fault کم نیست و به ازاء هر page-fault باید همه این ۶ مرحله طی شود. لذا بهتر است تا حد امکان از رخ دادن page-fault جلوگیری شود.

در شدیدترین حالت، می‌توان برنامه را بدون هیچ page بارگذاری شده داخل حافظه اجرا کرد. در این حالت احتمالا در ابتدای برنامه، به ازای هر instruction چند page-fault رخ دهد که بوضوح موجب کند شدن روند اجرا می‌شود. این روند در ادامه بهبود پیدا می‌کند، چون هر چه جلوتر می‌رود page های بیشتری از برنامه داخل حافظه بارگذاری شده‌اند و احتمالا page-fault کمتری رخ خواهد داد. به این روش اصطلاحا pure demand paging گفته می‌شود. یعنی تا وقتی به یک page نیاز نداریم، آن را داخل حافظه بارگذاری نکنیم.


سیستم‌عاملحافظه
شاید از این پست‌ها خوشتان بیاید