Implementation of all Partition Allocation Methods in Memory Management
Last Updated :
07 May, 2020
Prerequisite: Partition Allocation Methods in Memory Management
In
Partition Allocation, when there is more than one partition freely available to accommodate a process request, a partition must be selected. To choose a particular partition, a partition allocation method is needed. A partition allocation method is considered better if it avoids internal fragmentation.
Consider the following data for process:
Process No. |
Process Size |
1 |
88 |
2 |
192 |
3 |
277 |
4 |
365 |
5 |
489 |
Consider the following data for memory slots:
Memory Block No. |
Memory Block Size |
1 |
400 |
2 |
500 |
3 |
300 |
4 |
200 |
5 |
100 |
Below are the various partition allocation schemes with their implementation with respect to the given data above.
1. First Fit
This method keeps the free/busy list of jobs organized by memory location, low-ordered to high-ordered memory. In this method, the first job claims the first available memory with space more than or equal to its size. The operating system doesn’t search for appropriate partition but just allocate the job to the nearest memory partition available with sufficient size.
Below is the implementation of the
First Fit Algorithm:
CPP
// C++ program for the implementation
// of the First Fit algorithm
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Process Class
class process {
public:
// Size & number of process
size_t size;
pid_t no;
};
// Memory Class
class memory {
public:
size_t size;
// Number of memory & queue of space
// occupied by process
pid_t no;
queue<process> space_occupied;
// Function to push process in a block
void push(const process p)
{
if (p.size <= size) {
space_occupied.push(p);
size -= p.size;
}
}
// Function to pop and return the
// process from the block
process pop()
{
process p;
// If space occupied is empty
if (!space_occupied.empty()) {
p = space_occupied.front();
space_occupied.pop();
size += p.size;
return p;
}
}
// Function to check if block is
// completely empty
bool empty()
{
return space_occupied.empty();
}
};
// Function to get data of processess
// allocated using first fit
vector<memory> first_fit(vector<memory> memory_blocks,
queue<process> processess)
{
int i = 0;
bool done, done1;
memory na;
na.no = -10;
while (!processess.empty()) {
done = 0;
for (i = 0; i < memory_blocks.size(); i++) {
done1 = 0;
if (memory_blocks.at(i).size
>= processess.front().size) {
memory_blocks.at(i).push(processess.front());
done = 1;
done1 = 1;
break;
}
}
// If process is done
if (done == 0 && done1 == 0) {
na.size += processess.front().size;
na.push(processess.front());
}
// pop the process
processess.pop();
}
if (!na.space_occupied.empty())
memory_blocks.push_back(na);
return memory_blocks;
}
// Function to display the allocation
// of all processess
void display(vector<memory> memory_blocks)
{
int i = 0, temp = 0;
process p;
cout << "+-------------+--------------+--------------+"
<< endl;
cout << "| Process no. | Process size | Memory block |"
<< endl;
cout << "+-------------+--------------+--------------+"
<< endl;
// Traverse memory blocks size
for (i = 0; i < memory_blocks.size(); i++) {
// While memory block size is not empty
while (!memory_blocks.at(i).empty()) {
p = memory_blocks.at(i).pop();
temp = to_string(p.no).length();
cout << "|" << string(7 - temp / 2 - temp % 2, ' ')
<< p.no << string(6 - temp / 2, ' ')
<< "|";
temp = to_string(p.size).length();
cout << string(7 - temp / 2 - temp % 2, ' ')
<< p.size
<< string(7 - temp / 2, ' ') << "|";
temp = to_string(memory_blocks.at(i).no).length();
cout << string(7 - temp / 2 - temp % 2, ' ');
// If memory blocks is assigned
if (memory_blocks.at(i).no != -10) {
cout << memory_blocks.at(i).no;
}
// Else memory blocks is assigned
else {
cout << "N/A";
}
cout << string(7 - temp / 2, ' ')
<< "|" << endl;
}
}
cout << "+-------------+--------------+--------------+"
<< endl;
}
// Driver Code
int main()
{
// Declare memory blocks
vector<memory> memory_blocks(5);
// Declare first fit blocks
vector<memory> first_fit_blocks;
// Declare queue of all processess
queue<process> processess;
process temp;
// Set sample data
memory_blocks[0].no = 1;
memory_blocks[0].size = 400;
memory_blocks[1].no = 2;
memory_blocks[1].size = 500;
memory_blocks[2].no = 3;
memory_blocks[2].size = 300;
memory_blocks[3].no = 4;
memory_blocks[3].size = 200;
memory_blocks[4].no = 5;
memory_blocks[4].size = 100;
temp.no = 1;
temp.size = 88;
// Push the process
processess.push(temp);
temp.no = 2;
temp.size = 192;
// Push the process
processess.push(temp);
temp.no = 3;
temp.size = 277;
// Push the process
processess.push(temp);
temp.no = 4;
temp.size = 365;
// Push the process
processess.push(temp);
temp.no = 5;
temp.size = 489;
// Push the process
processess.push(temp);
// Get the data
first_fit_blocks = first_fit(memory_blocks, processess);
// Display the data
display(first_fit_blocks);
memory_blocks.clear();
memory_blocks.shrink_to_fit();
first_fit_blocks.clear();
first_fit_blocks.shrink_to_fit();
return 0;
}
Output:
+-------------+--------------+--------------+
| Process no. | Process size | Memory block |
+-------------+--------------+--------------+
| 1 | 88 | 1 |
| 2 | 192 | 1 |
| 3 | 277 | 2 |
| 4 | 365 | N/A |
| 5 | 489 | N/A |
+-------------+--------------+--------------+
2. Next Fit
The next fit is a modified version of ‘first fit’. It begins as the first fit to find a free partition but when called next time it starts searching from where it left off, not from the beginning. This policy makes use of a roving pointer. The pointer moves along the memory chain to search for a next fit. This helps in, to avoid the usage of memory always from the head (beginning) of the free block chain.
Below is the implementation of the
Next Fit Algorithm:
CPP
// C++ program for the implementation
// of the Next Fit algorithm
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Process Class
class process {
public:
// Size & number of process
size_t size;
pid_t no;
};
// Memory Class
class memory {
public:
size_t size;
// Number of memory & queue of space
// occupied by process
pid_t no;
queue<process> space_occupied;
// Function to push process in a block
void push(const process p)
{
if (p.size <= size) {
space_occupied.push(p);
size -= p.size;
}
}
// Function to pop and return the
// process from the block
process pop()
{
process p;
// If space occupied is empty
if (!space_occupied.empty()) {
p = space_occupied.front();
space_occupied.pop();
size += p.size;
return p;
}
}
// Function to check if block is
// completely empty
bool empty()
{
return space_occupied.empty();
}
};
// Function to get data of processess
// allocated using Next Fit
vector<memory> next_fit(vector<memory> memory_blocks,
queue<process> processess)
{
int i = 0;
bool done, done1;
memory na;
na.no = -10;
// Loop till process is empty
while (!processess.empty()) {
done1 = 0;
// Traverse memory_blocks
for (i = 0; i < memory_blocks.size(); i++) {
done = 0;
// If process is not empty
if (!processess.empty() && memory_blocks.at(i).size >= processess.front().size) {
memory_blocks.at(i).push(processess.front());
done = 1;
done1 = 1;
processess.pop();
}
}
if (!processess.empty() && done == 0 && done1 == 0) {
na.size += processess.front().size;
na.push(processess.front());
processess.pop();
}
}
// If space is not occupied push
// the memory_blocks na
if (!na.space_occupied.empty()) {
memory_blocks.push_back(na);
}
return memory_blocks;
}
// Function to display the allocation
// of all processess
void display(vector<memory> memory_blocks)
{
int i = 0, temp = 0;
process p;
cout << "+-------------+--------------+--------------+"
<< endl;
cout << "| Process no. | Process size | Memory block |"
<< endl;
cout << "+-------------+--------------+--------------+"
<< endl;
// Traverse memory blocks size
for (i = 0; i < memory_blocks.size(); i++) {
// While memory block size is not empty
while (!memory_blocks.at(i).empty()) {
p = memory_blocks.at(i).pop();
temp = to_string(p.no).length();
cout << "|" << string(7 - temp / 2 - temp % 2, ' ')
<< p.no << string(6 - temp / 2, ' ')
<< "|";
temp = to_string(p.size).length();
cout << string(7 - temp / 2 - temp % 2, ' ')
<< p.size
<< string(7 - temp / 2, ' ') << "|";
temp = to_string(memory_blocks.at(i).no).length();
cout << string(7 - temp / 2 - temp % 2, ' ');
// If memory blocks is assigned
if (memory_blocks.at(i).no != -10) {
cout << memory_blocks.at(i).no;
}
// Else memory blocks is assigned
else {
cout << "N/A";
}
cout << string(7 - temp / 2, ' ')
<< "|" << endl;
}
}
cout << "+-------------+--------------+--------------+"
<< endl;
}
// Driver Code
int main()
{
// Declare memory blocks
vector<memory> memory_blocks(5);
// Declare next fit blocks
vector<memory> next_fit_blocks;
// Declare queue of all processess
queue<process> processess;
process temp;
// Set sample data
memory_blocks[0].no = 1;
memory_blocks[0].size = 400;
memory_blocks[1].no = 2;
memory_blocks[1].size = 500;
memory_blocks[2].no = 3;
memory_blocks[2].size = 300;
memory_blocks[3].no = 4;
memory_blocks[3].size = 200;
memory_blocks[4].no = 5;
memory_blocks[4].size = 100;
temp.no = 1;
temp.size = 88;
// Push the process
processess.push(temp);
temp.no = 2;
temp.size = 192;
// Push the process
processess.push(temp);
temp.no = 3;
temp.size = 277;
// Push the process
processess.push(temp);
temp.no = 4;
temp.size = 365;
// Push the process
processess.push(temp);
temp.no = 5;
temp.size = 489;
// Push the process
processess.push(temp);
// Get the data
next_fit_blocks = next_fit(memory_blocks,
processess);
// Display the data
display(next_fit_blocks);
memory_blocks.clear();
memory_blocks.shrink_to_fit();
next_fit_blocks.clear();
next_fit_blocks.shrink_to_fit();
return 0;
}
Output:
+-------------+--------------+--------------+
| Process no. | Process size | Memory block |
+-------------+--------------+--------------+
| 1 | 88 | 1 |
| 2 | 192 | 2 |
| 3 | 277 | 3 |
| 4 | 365 | N/A |
| 5 | 489 | N/A |
+-------------+--------------+--------------+
3. Worst Fit
Worst Fit allocates a process to the partition which is largest sufficient among the freely available partitions available in the main memory. If a large process comes at a later stage, then memory will not have space to accommodate it.
Below is the implementation of the
Worst Fit Algorithm:
CPP
// C++ program for the implementation
// of the Worst Fit algorithm
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Process Class
class process {
public:
// Size & number of process
size_t size;
pid_t no;
};
// Memory Class
class memory {
public:
size_t size;
// Number of memory & queue of space
// occupied by process
pid_t no;
queue<process> space_occupied;
// Function to push process in a block
void push(const process p)
{
if (p.size <= size) {
space_occupied.push(p);
size -= p.size;
}
}
// Function to pop and return the
// process from the block
process pop()
{
process p;
// If space occupied is empty
if (!space_occupied.empty()) {
p = space_occupied.front();
space_occupied.pop();
size += p.size;
return p;
}
}
// Function to check if block is
// completely empty
bool empty()
{
return space_occupied.empty();
}
};
// Function to get data of processess
// allocated using Worst Fit
vector<memory> worst_fit(vector<memory> memory_blocks,
queue<process> processess)
{
int i = 0, index = 0, max;
memory na;
na.no = -10;
// Loop till process queue is not empty
while (!processess.empty()) {
max = 0;
// Traverse the memory_blocks
for (i = 0; i < memory_blocks.size(); i++) {
if (memory_blocks.at(i).size >= processess.front().size
&& memory_blocks.at(i).size > max) {
max = memory_blocks.at(i).size;
index = i;
}
}
if (max != 0) {
memory_blocks.at(index).push(processess.front());
}
else {
na.size += processess.front().size;
na.push(processess.front());
}
// Pop the current process
processess.pop();
}
// If space is not occupied
if (!na.space_occupied.empty()) {
memory_blocks.push_back(na);
}
// Return the memory
return memory_blocks;
}
// Function to display the allocation
// of all processess
void display(vector<memory> memory_blocks)
{
int i = 0, temp = 0;
process p;
cout << "+-------------+--------------+--------------+"
<< endl;
cout << "| Process no. | Process size | Memory block |"
<< endl;
cout << "+-------------+--------------+--------------+"
<< endl;
// Traverse memory blocks size
for (i = 0; i < memory_blocks.size(); i++) {
// While memory block size is not empty
while (!memory_blocks.at(i).empty()) {
p = memory_blocks.at(i).pop();
temp = to_string(p.no).length();
cout << "|" << string(7 - temp / 2 - temp % 2, ' ')
<< p.no << string(6 - temp / 2, ' ')
<< "|";
temp = to_string(p.size).length();
cout << string(7 - temp / 2 - temp % 2, ' ')
<< p.size
<< string(7 - temp / 2, ' ') << "|";
temp = to_string(memory_blocks.at(i).no).length();
cout << string(7 - temp / 2 - temp % 2, ' ');
// If memory blocks is assigned
if (memory_blocks.at(i).no != -10) {
cout << memory_blocks.at(i).no;
}
// Else memory blocks is assigned
else {
cout << "N/A";
}
cout << string(7 - temp / 2, ' ')
<< "|" << endl;
}
}
cout << "+-------------+--------------+--------------+"
<< endl;
}
// Driver Code
int main()
{
// Declare memory blocks
vector<memory> memory_blocks(5);
// Declare worst fit blocks
vector<memory> worst_fit_blocks;
// Declare queue of all processess
queue<process> processess;
process temp;
// Set sample data
memory_blocks[0].no = 1;
memory_blocks[0].size = 400;
memory_blocks[1].no = 2;
memory_blocks[1].size = 500;
memory_blocks[2].no = 3;
memory_blocks[2].size = 300;
memory_blocks[3].no = 4;
memory_blocks[3].size = 200;
memory_blocks[4].no = 5;
memory_blocks[4].size = 100;
temp.no = 1;
temp.size = 88;
// Push the process
processess.push(temp);
temp.no = 2;
temp.size = 192;
// Push the process
processess.push(temp);
temp.no = 3;
temp.size = 277;
// Push the process
processess.push(temp);
temp.no = 4;
temp.size = 365;
// Push the process
processess.push(temp);
temp.no = 5;
temp.size = 489;
// Push the process
processess.push(temp);
// Get the data
worst_fit_blocks = worst_fit(memory_blocks,
processess);
// Display the data
display(worst_fit_blocks);
memory_blocks.clear();
memory_blocks.shrink_to_fit();
worst_fit_blocks.clear();
worst_fit_blocks.shrink_to_fit();
return 0;
}
Output:
+-------------+--------------+--------------+
| Process no. | Process size | Memory block |
+-------------+--------------+--------------+
| 3 | 277 | 1 |
| 1 | 88 | 2 |
| 2 | 192 | 2 |
| 4 | 365 | N/A |
| 5 | 489 | N/A |
+-------------+--------------+--------------+
4. Best Fit
This method keeps the free/busy list in order by size – smallest to largest. In this method, the operating system first searches the whole of the memory according to the size of the given job and allocates it to the closest-fitting free partition in the memory, making it able to use memory efficiently. Here the jobs are in the order from smallest job to the largest job.
Below is the implementation of the
Best Fit Algorithm:
CPP
// C++ program for the implementation
// of the Best Fit algorithm
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Process Class
class process {
public:
// Size & number of process
size_t size;
pid_t no;
};
// Memory Class
class memory {
public:
size_t size;
// Number of memory & queue of space
// occupied by process
pid_t no;
queue<process> space_occupied;
// Function to push process in a block
void push(const process p)
{
if (p.size <= size) {
space_occupied.push(p);
size -= p.size;
}
}
// Function to pop and return the
// process from the block
process pop()
{
process p;
// If space occupied is empty
if (!space_occupied.empty()) {
p = space_occupied.front();
space_occupied.pop();
size += p.size;
return p;
}
}
// Function to check if block is
// completely empty
bool empty()
{
return space_occupied.empty();
}
};
// Function to get data of processess
// allocated using Best Fit
vector<memory> best_fit(vector<memory> memory_blocks,
queue<process> processess)
{
int i = 0, min, index = 0;
memory na;
na.no = -10;
// Loop till processe is not empty
while (!processess.empty()) {
min = 0;
// Traverse the memory_blocks
for (i = 0; i < memory_blocks.size(); i++) {
if (memory_blocks.at(i).size >= processess.front().size && (min == 0 || memory_blocks.at(i).size < min)) {
min = memory_blocks.at(i).size;
index = i;
}
}
if (min != 0) {
memory_blocks.at(index).push(processess.front());
}
else {
na.size += processess.front().size;
na.push(processess.front());
}
// Pop the processe
processess.pop();
}
// If space is no occupied then push
// the current memory na
if (!na.space_occupied.empty()) {
memory_blocks.push_back(na);
}
// Return the memory_blocks
return memory_blocks;
}
// Function to display the allocation
// of all processess
void display(vector<memory> memory_blocks)
{
int i = 0, temp = 0;
process p;
cout << "+-------------+--------------+--------------+"
<< endl;
cout << "| Process no. | Process size | Memory block |"
<< endl;
cout << "+-------------+--------------+--------------+"
<< endl;
// Traverse memory blocks size
for (i = 0; i < memory_blocks.size(); i++) {
// While memory block size is not empty
while (!memory_blocks.at(i).empty()) {
p = memory_blocks.at(i).pop();
temp = to_string(p.no).length();
cout << "|" << string(7 - temp / 2 - temp % 2, ' ')
<< p.no << string(6 - temp / 2, ' ')
<< "|";
temp = to_string(p.size).length();
cout << string(7 - temp / 2 - temp % 2, ' ')
<< p.size
<< string(7 - temp / 2, ' ') << "|";
temp = to_string(memory_blocks.at(i).no).length();
cout << string(7 - temp / 2 - temp % 2, ' ');
// If memory blocks is assigned
if (memory_blocks.at(i).no != -10) {
cout << memory_blocks.at(i).no;
}
// Else memory blocks is assigned
else {
cout << "N/A";
}
cout << string(7 - temp / 2, ' ')
<< "|" << endl;
}
}
cout << "+-------------+--------------+--------------+"
<< endl;
}
// Driver Code
int main()
{
// Declare memory blocks
vector<memory> memory_blocks(5);
// Declare best fit blocks
vector<memory> best_fit_blocks;
// Declare queue of all processess
queue<process> processess;
process temp;
// Set sample data
memory_blocks[0].no = 1;
memory_blocks[0].size = 400;
memory_blocks[1].no = 2;
memory_blocks[1].size = 500;
memory_blocks[2].no = 3;
memory_blocks[2].size = 300;
memory_blocks[3].no = 4;
memory_blocks[3].size = 200;
memory_blocks[4].no = 5;
memory_blocks[4].size = 100;
temp.no = 1;
temp.size = 88;
// Push the processe to queue
processess.push(temp);
temp.no = 2;
temp.size = 192;
// Push the processe to queue
processess.push(temp);
temp.no = 3;
temp.size = 277;
// Push the processe to queue
processess.push(temp);
temp.no = 4;
temp.size = 365;
// Push the processe to queue
processess.push(temp);
temp.no = 5;
temp.size = 489;
// Push the processe to queue
processess.push(temp);
// Get the data
best_fit_blocks = best_fit(memory_blocks,
processess);
// Display the data
display(best_fit_blocks);
memory_blocks.clear();
memory_blocks.shrink_to_fit();
best_fit_blocks.clear();
best_fit_blocks.shrink_to_fit();
return 0;
}
Output:
+-------------+--------------+--------------+
| Process no. | Process size | Memory block |
+-------------+--------------+--------------+
| 4 | 365 | 1 |
| 5 | 489 | 2 |
| 3 | 277 | 3 |
| 2 | 192 | 4 |
| 1 | 88 | 5 |
+-------------+--------------+--------------+
Similar Reads
Implementation of file allocation methods using vectors
Prerequisite: File Allocation Methods Different File Allocation methods: 1. Contiguous File Allocation Methods: This is a type of allocation in which a file occupies contiguous blocks of a given memory. This type of allocation is fastest because we can access any part of the file just by adding it t
15+ min read
Implementation of Quick sort using MPI, OMP and Posix thread
QuickSort is a Divide and Conquer Algorithm. It picks an element as a pivot and partitions the array around the picked pivot. There are many ways of choosing the pivot elements. They are: Always pick the first element as a pivot.Always pick the last element as the pivot (implemented below)Pick a ran
15+ min read
Difference Between Stack-Allocated and Heap-Allocated Arrays
In C/C++, arrays can be allocated in two areas of memory: the stack and the heap. Each has its own characteristics and use cases. In this article, we will see the key differences between stack-allocated and heap-allocated arrays. Stack-Allocated ArraysThe arrays declared as static arrays in the func
3 min read
Difference Between Pointers and Array Notations in C++
In C++, pointers and array notations are two ways using which we work with arrays and memory for accessing the data. They have distinct behaviours and are used in different contexts. In this article, we will learn the key differences between pointers and array notations in C++. Difference Between Po
4 min read
Creating array of pointers in C++
An array of pointers is an array of pointer variables. It is also known as pointer arrays. We will discuss how to create a 1D and 2D array of pointers dynamically. The word dynamic signifies that the memory is allocated during the runtime, and it allocates memory in Heap Section. In a Stack, memory
5 min read
Data type of a Pointer in C++
A pointer is a variable that stores the memory address of an object. The pointer then simply âpointsâ to the object. The type of the object must correspond with the type of the pointer. Pointers are used extensively in both C and C++ for three main purposes: To allocate new objects on the heap.To pa
5 min read
C/C++ Divide and Conquer Programs
The divide and conquer is an algorithmic approach to solve problems by dividing them into smaller sub-problems, solving them, and then constructing the complete solution using the solution of smaller sub-problems. This approach uses the recursion to divide the problem into smaller subproblems and it
2 min read
Stack and Queue C/C++ Programs
The stack and queue are popular linear data structures with a wide variety of applications. The stack follows LIFO (Last In First Out) principle where the data is inserted and extracted from the same side. On the other hand, the queue follows FIFO (First In First Out) principle, i.e., data is insert
3 min read
Array C/C++ Programs
C Program to find sum of elements in a given arrayC program to find largest element in an arrayC program to multiply two matricesC/C++ Program for Given an array A[] and a number x, check for pair in A[] with sum as xC/C++ Program for Majority ElementC/C++ Program for Find the Number Occurring Odd N
6 min read
C/C++ Programs
sArray C/C++ ProgramsC Program to find sum of elements in a given arrayC program to find largest element in an arrayRecursive C program to linearly search an element in a given arrayC program to multiply two matricesC/C++ Program for Given an array A[] and a number x, check for pair in A[] with sum
15+ min read