Browse Source

:bug: 修复malloc扩容时int32溢出的bug,以及扩容堆内存后,由于未执行合并从而导致产生大量碎片的bug

fslongjin 2 years ago
parent
commit
46ee327742
3 changed files with 25 additions and 16 deletions
  1. 8 7
      kernel/mm/mm.c
  2. 5 5
      user/init.c
  3. 12 4
      user/libs/libc/malloc.c

+ 8 - 7
kernel/mm/mm.c

@@ -177,6 +177,7 @@ void mm_init()
         }
     }
 
+
     // 初始化0~2MB的物理页
     // 由于这个区间的内存由多个内存段组成,因此不会被以上代码初始化,需要我们手动配置page[0]。
 
@@ -195,6 +196,7 @@ void mm_init()
     ZONE_NORMAL_INDEX = 0;
     ZONE_UNMAPPED_INDEX = 0;
 
+    /*
     for (int i = 0; i < memory_management_struct.count_zones; ++i)
     {
         struct Zone *z = memory_management_struct.zones_struct + i;
@@ -202,9 +204,10 @@ void mm_init()
         //             z->zone_addr_start, z->zone_addr_end, z->zone_length, z->pages_group, z->count_pages);
 
         // 1GB以上的内存空间不做映射
-        if (z->zone_addr_start >= 0x100000000 && (!ZONE_UNMAPPED_INDEX))
-            ZONE_UNMAPPED_INDEX = i;
+        // if (z->zone_addr_start >= 0x100000000 && (!ZONE_UNMAPPED_INDEX))
+        //    ZONE_UNMAPPED_INDEX = i;
     }
+    */
     // kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
     //  设置内存页管理结构的地址,预留了一段空间,防止内存越界。
     memory_management_struct.end_of_struct = (ul)((ul)memory_management_struct.zones_struct + memory_management_struct.zones_struct_len + sizeof(long) * 32) & (~(sizeof(long) - 1));
@@ -230,7 +233,6 @@ void mm_init()
         --tmp_page->zone->count_pages_free;
     }
 
-  
     kinfo("Memory management unit initialize complete!");
 
     flush_tlb();
@@ -311,7 +313,6 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
             continue;
 
         struct Zone *z = memory_management_struct.zones_struct + i;
-
         // 区域对应的起止页号
         ul page_start = (z->zone_addr_start >> PAGE_2M_SHIFT);
         ul page_end = (z->zone_addr_end >> PAGE_2M_SHIFT);
@@ -350,6 +351,8 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
             }
         }
     }
+    kBUG("Cannot alloc page, ZONE=%d\tnums=%d, total_2M_pages=%d", zone_select, num, total_2M_pages);
+    while(1);
     return NULL;
 }
 
@@ -470,7 +473,7 @@ void page_table_init()
         struct Zone *z = memory_management_struct.zones_struct + i;
         struct Page *p = z->pages_group;
 
-        if (i == ZONE_UNMAPPED_INDEX)
+        if (i == ZONE_UNMAPPED_INDEX && ZONE_UNMAPPED_INDEX != 0)
             break;
 
         for (int j = 0; j < z->count_pages; ++j)
@@ -484,8 +487,6 @@ void page_table_init()
     kinfo("Page table Initialized.");
 }
 
-
-
 /**
  * @brief 将物理地址映射到页表的函数
  *

+ 5 - 5
user/init.c

@@ -36,16 +36,16 @@ int main()
     void *ptr[256] = {0};
     for (int k = 0; k < 2; ++k)
     {
-        printf("try to malloc 256*16K=4MB\n");
+        printf("try to malloc 256*1M=256MB\n");
         uint64_t js = 0;
         for (int i = 0; i < 256; ++i)
         {
-            ptr[i] = malloc(4096 * 4);
+            ptr[i] = malloc(1024 * 1024);
             js += *(uint64_t *)((uint64_t)(ptr[i]) - sizeof(uint64_t));
-            if (*(uint64_t *)((uint64_t)(ptr[i]) - sizeof(uint64_t)) > 0x4008)
-                printf("[%d] start_addr = %#018lx, len = %#010lx\n", (uint64_t)(ptr[i]) - 8, *(uint64_t *)((uint64_t)(ptr[i]) - sizeof(uint64_t)));
+            // if (*(uint64_t *)((uint64_t)(ptr[i]) - sizeof(uint64_t)) > 0x4008)
+            //     printf("[%ld] start_addr = %#018lx, len = %#010lx\n", i, (uint64_t)(ptr[i]) - 8, *(uint64_t *)((uint64_t)(ptr[i]) - sizeof(uint64_t)));
         }
-       
+
         // printf("ptr[0]->len=%lld\n", *(uint64_t *)((uint64_t)ptr[0] - sizeof(uint64_t)));
         // printf("ptr[1]->len=%lld\n", *(uint64_t *)((uint64_t)ptr[1] - sizeof(uint64_t)));
         //  printf("ptr[24]->len=%lld\n", *(uint64_t*)((uint64_t)ptr[24] - sizeof(uint64_t)));

+ 12 - 4
user/libs/libc/malloc.c

@@ -127,7 +127,7 @@ static malloc_mem_chunk_t *malloc_query_free_chunk_ff(uint64_t size)
  *
  * @param size 扩大的内存大小
  */
-static int malloc_enlarge(int32_t size)
+static int malloc_enlarge(int64_t size)
 {
     if (brk_base_addr == 0) // 第一次调用,需要初始化
     {
@@ -292,6 +292,9 @@ void *malloc(ssize_t size)
 
         if (malloc_enlarge(size) == -ENOMEM)
             return (void *)-ENOMEM; // 内存不足
+
+        malloc_merge_free_chunk(); // 扩容后运行合并,否则会导致碎片
+
         // 扩容后再次尝试获取
 
         ck = malloc_query_free_chunk_bf(size);
@@ -326,7 +329,6 @@ found:;
         malloc_insert_free_list(new_ck);
     }
 
-
     // 此时链表结点的指针的空间被分配出去
     return (void *)((uint64_t)ck + sizeof(uint64_t));
 }
@@ -340,11 +342,17 @@ static void release_brk()
     // 先检测最顶上的块
     // 由于块按照开始地址排列,因此找最后一个块
     if (malloc_free_list_end == NULL)
+    {
+        printf("release(): free list end is null. \n");
         return;
+    }
     if ((uint64_t)malloc_free_list_end + malloc_free_list_end->length == brk_max_addr && (uint64_t)malloc_free_list_end <= brk_max_addr - (PAGE_2M_SIZE << 1))
     {
-        int64_t delta = (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK - PAGE_2M_SIZE;
-
+        int64_t delta = ((brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK) - PAGE_2M_SIZE;
+        // printf("(brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK=%#018lx\n ", (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK);
+        // printf("PAGE_2M_SIZE=%#018lx\n", PAGE_2M_SIZE);
+        // printf("tdfghgbdfggkmfn=%#018lx\n ", (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK - PAGE_2M_SIZE);
+        // printf("delta=%#018lx\n ", delta);
         if (delta <= 0) // 不用释放内存
             return;
         sbrk(-delta);