# 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: ﬁrst-ﬁt, best-ﬁt, và worst-ﬁt.

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

<table data-header-hidden><thead><tr><th></th><th width="293.33333333333337"></th><th></th></tr></thead><tbody><tr><td><strong>Yêu cầu</strong></td><td><strong>Kích thước hố nhớ được chọn</strong></td><td><strong>Các kích thước hố nhớ còn lại</strong></td></tr><tr><td>115KB</td><td>750KB</td><td>300KB, 600KB, 350KB, 200KB, 635KB, 125KB</td></tr><tr><td>500KB</td><td>635KB</td><td>300KB, 600KB, 350KB, 200KB, 135KB, 125KB</td></tr><tr><td>358KB</td><td>600KB</td><td>300KB, 242KB, 350KB, 200KB, 135KB, 125KB</td></tr><tr><td>200KB</td><td>350KB</td><td>300KB, 242KB, 150KB, 200KB, 135KB, 125KB</td></tr><tr><td>375KB</td><td><mark style="color:red;"><strong>Không thể thực thi</strong></mark></td><td>300KB, 242KB, 150KB, 200KB, 135KB, 125KB</td></tr></tbody></table>

### <mark style="color:blue;">Chương trình minh họa giải thuật First-Fit</mark>

```
#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

![](/files/xyTJE7BbDbi6BMPVqjNG)

### <mark style="color:blue;">Chương trình minh họa giải thuật Best-Fit</mark>

```
#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

![](/files/2LJECjgs5lQJciUUmKNF)

### <mark style="color:blue;">Chương trình minh họa giải thuật Worst-Fit</mark>

```
#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

![](/files/AZDXoWxyY4kn5tSaCjoz)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://minilessons.gitbook.io/lessons/thuc-hanh-he-dieu-hanh/bo-nho-chinh.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
