در قسمت قبل به طور خلاصه به برخی مفاهیم پایه در مدیریت حافظه توسط سیستمعامل پرداختیم. در این بخش در موضوع مدیریت حافظه اندکی بیشتر عمیق میشویم و با مفهوم «تخصیص پیوسته حافظه» آشنا میشویم.
حافظه کامپیوتر، از تعدادی بایت تشکیل شده که هر کدام آدرس مشخصی دارند. آدرس خانههای حافظه از ۰ شروع میشود و جلو میرود. این یعنی برای دسترسی به یک خانه از حافظه، تنها به یک عدد - آدرس آن خانه از حافظه - نیاز داریم. این مسئله باعث میشود نوع تخصیص خانههای حافظه مهم باشد.
در تخصیص پیوسته حافظه، سیستمعامل بلوکهای مجاور حافظه را به پروسهها تخصیص میدهد. در ابتدای امر، کل حافظه دستنخورده است. البته منظور از کل حافظه، بخش مربوط به پروسههای کاربر است، یعنی احتمالا بخشهای پایینی حافظه (حافظه، به طور کلی به دو بخش kernel space و user space تقسیم میشود، که اولی حافظه متعقل به سیستمعامل است و دومی حافظه متعلق به پروسههای مربوط به کاربر. بدیهی است که از بدو اجرا سیستمعامل، بخش kernel space مورد استفاده قرار میگیرد). حالا وقتی یک پروسه از سیستمعامل مقدار معینی حافظه درخواست میکند، سیستمعامل از اولین خانه خالی تا جای مورد نیاز را به طور پیوسته در اختیار این پروسه قرار میدهد. وقتی پروسه دومی دوباره از سیستمعامل درخواست حافظه کند، سیستمعامل از آخرین حافظه اشغال شده توسط پروسه اول، تا جایی که لازم است را در اختیار پروسه جدید قرار میدهد. بدین معنا که هیچ حافظه بلااستفادهای بین حافظه تخصیص یافته به پروسه اول و دوم نیست. این دو بخش کاملا در مجاورت یکدیگر قرار دارند.
این روند تا جایی پیشمیرود که کل حافظه پر شود. در این حین، ممکن است بعضی از پروسههای قبلی که حافظه را اشغال کردهاند، کارشان تمام شود و حافظه را آزاد کنند. چالش اصلی استفاده مجدد از این بخشهای آزاد شده است.
اصطلاحا به بخشهایی از حافظه که خالی و آزاد هستند (توسط هیچ پروسهای اشغال نشدهاند) سوراخ یا hole گفته میشود. در طول اجرای پروسههای مختلف و اتمام کار آنها، سوراخهای زیادی در حافظه ایجاد میشود. این سوراخها اندازههای متغییر دارند. و این باعث میشود که مقدار زیادی حافظه خالی و آزاد باشد. وقتی پروسه جدیدی ایجاد شود، از سیستمعامل درخواست حافظه میکند. سیستمعامل بخشهای استفاده نشده (همان سوراخها) حافظه را بررسی میکند، اگر هرکدام به اندازه حافظه مورد نیاز پروسه بود، آن بخش را در اختیار آن پروسه قرار میدهد. تصویر زیر تا حدی این مسئله را شفاف میکند.
در تصویر بالا نشان داده میشود که پروسه ۸ به اتمام میرسد و یک سوراخ در حافظه ایجاد میشود. در مرحله بعد پروسه ۹ وارد حافظه میشود و بخشی از فضای استفاده نشده را استفاده میکند. در مرحله بعد پروسه ۵ از مدار خارج میشود و سوراخ دیگری در حافظه ایجاد میشود.
اما مشکل اصلی این است که این بخشهای بلااستفاده از حافظه در کنار یکدیگر نیستند و در کل حافظه پخش هستند. این باعث میشود که نتوانیم به طور بهینه از آنها استفاده کنیم. همانطور که در تصویر بالا مشخص است، ما در مرحله آخر، ۲ تکه بلااستفاده از حافظه را داریم که در مجاورت یکدیگر نیستند. به عبارتی پیوسته نیستند. اگر پروسه جدیدی درخواست حافظه داشته باشد، سیستمعامل باید ببیند آیا هر کدام از این بخشها کفاف این پروسه را خواهند داد یا خیر. ممکن است مجموع این سوراخها نیاز پروسه جدید را رفع کنند، اما به این دلیل که این بخشها در مجاورت یکدیگر نیستند، نمیتوانیم از آنها استفاده کنیم.
یعنی ممکن است در طول اجرا پروسهها، به جایی برسیم حجم زیادی از حافظه آزاد است، اما به این دلیل که این بخشها بین پروسههای مختلف پخش هستند و یکپارچه نیستند، نمیتوان از آنها استفاده کرد. به اتلاف حافظه آزاد اما غیرقابل استفاده اصطلاحا external-fragmentation گفته میشود. بدترین حالت external-fragmentation این است که بین هر دو پروسه، مقداری حافظه آزاد وجود داشته باشد.
به عبارتی، در تخصیص پیوسته حافظه، هر پروسه، باید در خانههای مجاور حافظه مستقر باشد. این مسئله از جهاتی سرعت پردازش آن پروسه را بالاتر میبرد، اما از طرف دیگر استفاده بهینه از حافظه یک چالش خواهد بود.
وقتی یک پروسه از سیستمعامل درخواست حافظه میکند، سیستمعامل باید بین بخشهای آزاد حافظه، یک سوراخ (یا بخشی از یک سوراخ) را در اختیار آن پروسه قرار دهد. اینکه سیستمعامل کدام بخش را در اختیار پروسه قرار میدهد، استراتژی سیستمعامل است. به طور کلی سه نوع مسیر برای تخصیص حافظه به پروسهها وجود دارد:
طبیعی است که مورد آخر بهینه نیست. اما بین دو مورد best-fit و first-fit کاملا مشخص نیست کدام بهتر هستند. اگرچه best-fit استفاده بهینهتری از حافظه میکند، اما زمان بیشتری طول میکشد تا سیستمعامل بهترین گزینه را انتخاب کند. برعکس، در حالت first-fit سیستمعامل اولین بخش مناسب را انتخاب میکند و این زمان خیلی کمتری خواهد برد.