BỘ NHỚ CHÍNH

Quản lý bộ nhớ là chức năng của hệ điều hành trong việc xử lý và di chuyển các tiến trình qua lại giữa bộ nhớ chính và đĩa trong quá trình thực thi. Hệ điều hành theo dõi từng vị trí bộ nhớ, bất kể nó được cấp phát cho một số tiến trình hay nó đang trống. Hệ điều hành kiểm tra lượng bộ nhớ được cấp cho các tiến trình. Nó quyết định tiến trình nào sẽ nhận được bộ nhớ vào thời điểm nào. Nó theo dõi bất cứ khi nào một số bộ nhớ được giải phóng hoặc không được cấp phát và tương ứng nó sẽ cập nhật trạng thái.

Bài học này giúp các bạn chạy thử các giải thuật cấp phát bộ nhớ chính trong hệ điều hành. Cụ thể các bạn sẽ viết và chạy các thuật toán cấp phát bộ nhớ là: FirstFit, BestFit và WorstFit.

Trước khi viết chương trình minh họa, chúng ta cùng khảo sát một ví dụ để phân tích việc cấp phát bộ nhớ bằng các thuật toán đã đề cập ở trên.

Bài toán: Cho 6 phân vùng nhớ theo thứ tự: 300 KB, 600 KB, 350 KB, 200 KB, 750 KB, và 125 KB. Các tiến trình với kích thước theo thứ tự: 115 KB, 500 KB, 358 KB, 200 KB, và 375 KB sẽ được cấp phát bộ nhớ như thế nào theo các giải thuật: first-fit, best-fit, và worst-fit.

Bảng phân tích việc cấp phát bộ nhớ theo các thuật toán như sau:

Theo giải thuật First-fit

Yêu cầu (Kích thước tiến trình)

Kích thước hole được chọn

Các kích thước hole còn lại

115KB

300KB

185KB, 600KB, 350KB, 200KB, 750KB, 125KB

500KB

600KB

185KB, 100KB, 350KB, 200KB, 750KB, 125KB

358KB

750KB

185KB, 100KB, 350KB, 200KB, 392KB, 125KB

200KB

350KB

185KB, 100KB, 150KB, 200KB, 392KB, 125KB

375KB

392KB

185KB, 100KB, 150KB, 200KB, 17KB, 125KB

Theo giải thuật Best-fit

Yêu cầu

Kích thước hố nhớ được chọn

Các kích thước hố nhớ còn lại

115KB

125KB

300KB, 600KB, 350KB, 200KB, 750KB, 10KB

500KB

600KB

300KB, 100KB, 350KB, 200KB, 750KB, 10KB

358KB

750KB

300KB, 100KB, 350KB, 200KB, 392KB, 10KB

200KB

200KB

300KB, 100KB, 350KB, 392KB, 10KB

375KB

392KB

300KB, 100KB, 350KB, 17KB, 10KB

Theo giải thuật Worst-fit

Yêu cầu

Kích thước hố nhớ được chọn

Các kích thước hố nhớ còn lại

115KB

750KB

300KB, 600KB, 350KB, 200KB, 635KB, 125KB

500KB

635KB

300KB, 600KB, 350KB, 200KB, 135KB, 125KB

358KB

600KB

300KB, 242KB, 350KB, 200KB, 135KB, 125KB

200KB

350KB

300KB, 242KB, 150KB, 200KB, 135KB, 125KB

375KB

Không thể thực thi

300KB, 242KB, 150KB, 200KB, 135KB, 125KB

Chương trình minh họa giải thuật First-Fit

#include<stdio.h>
 
int main()
{
      static int khoinho[10], tientrinh[10];
      int phanmanh[10], kichthuockhoi[10], kichthuoctientrinh[10];
      int m, n, sokhoi, sotientrinh, temp;
      printf("\nNhập tổng số khối nhớ:");
      scanf("%d", &sokhoi);
      printf("Nhập tổng số tiến trình:");
      scanf("%d", &sotientrinh);
      printf("\nNhập kích thước (dung lượng) của mỗi khối nhớ:\n");
      for(m = 0; m < sokhoi; m++) 
      {
            printf("Khối.[%d]:", m+1);
            scanf("%d", &kichthuockhoi[m]);
      }
      printf("Nhập kích thước của mỗi tiến trình:\n");
      for(m = 0; m < sotientrinh; m++) 
      {
            printf("Tiến trình.[%d]:", m+1);
            scanf("%d", &kichthuoctientrinh[m]);
      }
      for(m = 0; m < sotientrinh; m++)
      {
            for(n = 0; n < sokhoi; n++)
            {
                  if(kichthuockhoi[n] >= kichthuoctientrinh[m])
                  {
                        khoinho[m]=n;
                        kichthuockhoi[n]=kichthuockhoi[n] - kichthuoctientrinh[m];
                        temp=kichthuockhoi[n];
                        tientrinh[m] = n;
                        
                        break;
                        
                  }
            }
            phanmanh[m] = temp;
            
            
      }
      printf("\nTiến trình\t\tKích thước tiến trình\t\tKhối nhớ\t\tPhân mảnh");
      for(m = 0; m < sotientrinh; m++)
      {
            printf("\n%d\t\t\t%d\t\t\t\t%d\t\t\t%d", m+1, kichthuoctientrinh[m],tientrinh[m]+1, phanmanh[m]);
      }
      printf("\n");
      return 0;
}

Kết quả chạy chương trình trên hệ điều hành CentOS, biên dịch bằng GCC

Chương trình minh họa giải thuật Best-Fit

#include <stdio.h>
#include <string.h>

/*Hàm nhập mảng 1 chiều*/
void nhapmang(int array[], int length){
    for (short i = 0; i < length; i++)
    {
        printf("Kích thước thứ %d:",i+1);
        scanf("%d", &array[i]);
    }
}

void bestFit(int kichthuockhoi[], int m, int kichthuoctientrinh[], int n)
{
	//Mảng lưu trữ thứ tự các khối nhớ
	int khoinho[n];
    
    //Khởi tạo CHƯA có khối nhớ nào được cấp cho tiến trình
    memset(khoinho, -1, sizeof(khoinho)); 
    /*
        Hàm memset() trong C được sử dụng để lấp đầy một khối bộ nhớ với một giá trị cụ thể.
        Cú pháp của hàm memset() như sau: 
        void * memset (void * ptr, int x, size_t n);
            ptr:    Địa chỉ bắt đầu của bộ nhớ sẽ được lấp đầy
            x:      Giá trị được điền
            n:      Số byte được điền bắt đầu từ con trỏ ptr
    */

	
	//Chọn từng tiến trình và duyệt tìm khối có kích thước phù hợp với nó nhất
	for (int i=0; i<n; i++)
	{
		// Tìm khối nhớ đủ và tốt nhất cho tiến trình
		int khoitotnhat = -1;
		for (int j=0; j<m; j++)
		{
			if (kichthuockhoi[j] >= kichthuoctientrinh[i])
			{
				if (khoitotnhat == -1)
					khoitotnhat = j;
				else if (kichthuockhoi[khoitotnhat] > kichthuockhoi[j])
					khoitotnhat = j;
			}
		}

		// Khi tìm thấy khối nhớ tốt nhất cho tiến trình hiện hành
		if (khoitotnhat != -1)
		{
			// Cấp phát khối nhớ j cho tiến trình p[i]
			khoinho[i] = khoitotnhat;

			// Giảm kích thước cho khối nhớ này.
			kichthuockhoi[khoitotnhat] -= kichthuoctientrinh[i];
		}
	}

	
	printf("\nTiến trình\tKích thước\tKhối nhớ số\n");
	for (int i = 0; i < n; i++)
	{
		printf("\n%d\t\t\%d\t\t", i+1, kichthuoctientrinh[i]);
		if (khoinho[i] != -1)
			printf("%d",khoinho[i] + 1);
		else
			printf("Chưa được cấp phát\n");
		
	}
}


int main(){
    int sokhoi,sotientrinh;
    printf("Nhập số khối nhớ: ");
    scanf("%d", &sokhoi);
 
    int mang1[sokhoi];
    printf("Nhập kích thước cho mỗi khối nhớ:\n");
    nhapmang(mang1, sokhoi);
    printf("Nhập số tiến trình: ");
    scanf("%d", &sotientrinh);
 
    int mang2[sotientrinh];
    printf("Nhập kích thước cho mỗi tiến trình:\n");
    nhapmang(mang2, sotientrinh);
    
    bestFit(mang1, sokhoi, mang2, sotientrinh);
    

	return 0 ;
}

Kết quả chạy chương trình trên hệ điều hành CentOS, biên dịch bằng GCC

Chương trình minh họa giải thuật Worst-Fit

#include <stdio.h>
#include <string.h>

/*Hàm nhập mảng 1 chiều*/
void nhapmang(int array[], int length){
    for (short i = 0; i < length; i++)
    {
        printf("Kích thước thứ %d:",i+1);
        scanf("%d", &array[i]);
    }
}

void WorstFit(int kichthuockhoi[], int m, int kichthuoctientrinh[], int n)
{
	//Mảng lưu trữ thứ tự các khối nhớ
	int khoinho[n];
    
    //Khởi tạo CHƯA có khối nhớ nào được cấp cho tiến trình
    memset(khoinho, -1, sizeof(khoinho)); 
    /*
        Hàm memset() trong C được sử dụng để lấp đầy một khối bộ nhớ với một giá trị cụ thể.
        Cú pháp của hàm memset() như sau: 
        void * memset (void * ptr, int x, size_t n);
            ptr:    Địa chỉ bắt đầu của bộ nhớ sẽ được lấp đầy
            x:      Giá trị được điền
            n:      Số byte được điền bắt đầu từ con trỏ ptr
    */

	
	//Chọn từng tiến trình và duyệt tìm khối có kích thước phù hợp với nó nhất
	for (int i=0; i<n; i++)
	{
		// Tìm khối nhớ to nhất cho tiến trình
		int khoitonhat = -1;
		for (int j=0; j<m; j++)
		{
			if (kichthuockhoi[j] >= kichthuoctientrinh[i])
			{
				if (khoitonhat == -1)
					khoitonhat = j;
				else if (kichthuockhoi[khoitonhat] < kichthuockhoi[j])
					khoitonhat = j;
			}
		}

		// Khi tìm thấy khối nhớ to nhất cho tiến trình hiện hành
		if (khoitonhat != -1)
		{
			// Cấp phát khối nhớ j cho tiến trình p[i]
			khoinho[i] = khoitonhat;

			// Giảm kích thước cho khối nhớ này.
			kichthuockhoi[khoitonhat] = kichthuockhoi[khoitonhat] - kichthuoctientrinh[i];
		}
	}

	
	printf("\nTiến trình\tKích thước\tKhối nhớ số\n");
	for (int i = 0; i < n; i++)
	{
		printf("\n%d\t\t\%d\t\t", i+1, kichthuoctientrinh[i]);
		if (khoinho[i] != -1)
			printf("%d",khoinho[i] + 1);
		else
			printf("Chưa được cấp phát\n");
		
	}
}


int main(){
    int sokhoi,sotientrinh;
    printf("Nhập số khối nhớ: ");
    scanf("%d", &sokhoi);
 
    int mang1[sokhoi];
    printf("Nhập kích thước cho mỗi khối nhớ:\n");
    nhapmang(mang1, sokhoi);
    printf("Nhập số tiến trình: ");
    scanf("%d", &sotientrinh);
 
    int mang2[sotientrinh];
    printf("Nhập kích thước cho mỗi tiến trình:\n");
    nhapmang(mang2, sotientrinh);
    
    WorstFit(mang1, sokhoi, mang2, sotientrinh);
    

	return 0 ;
}

Kết quả chạy chương trình trên hệ điều hành CentOS, biên dịch bằng GCC

Last updated