diff --git a/.vscode/settings.json b/.vscode/settings.json index d427ee94..49147e40 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,8 @@ "asm.h": "c", "memory.h": "c", "irq.h": "c", - "multiboot2.h": "c" + "multiboot2.h": "c", + "kprint.h": "c", + "8259a.h": "c" } } \ No newline at end of file diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index b5bfd079..7fad2806 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -18,7 +18,7 @@ void mm_init() struct multiboot_mmap_entry_t *mb2_mem_info; int count; multiboot2_iter(multiboot2_get_memory, mb2_mem_info, &count); - + for (int i = 0; i < count; ++i) { //可用的内存 @@ -68,7 +68,7 @@ void mm_init() memory_management_struct.bmp_len = (((unsigned long)(max_addr >> PAGE_2M_SHIFT) + sizeof(unsigned long) * 8 - 1) / 8) & (~(sizeof(unsigned long) - 1)); // bmp由多少个unsigned long变量组成 // 初始化bitmap, 先将整个bmp空间全部置位。稍后再将可用物理内存页复位。 - memset(memory_management_struct.bmp, 0xff, memory_management_struct.bmp_len); + memset(memory_management_struct.bmp, 0xffffffffffffffff, memory_management_struct.bmp_len); // 初始化内存页结构 // 将页结构映射于bmp之后 @@ -184,18 +184,6 @@ void mm_init() global_CR3 = get_CR3(); - /* - printk_color(INDIGO, BLACK, "cr3:\t%#018lx\n", cr3); - printk_color(INDIGO, BLACK, "*cr3:\t%#018lx\n", *(phys_2_virt(cr3)) & (~0xff)); - printk_color(INDIGO, BLACK, "**cr3:\t%#018lx\n", *phys_2_virt(*(phys_2_virt(cr3)) & (~0xff)) & (~0xff)); - */ - - /* - // 消除一致性页表映射,将页目录(PML4E)的前10项清空 - for (int i = 0; i < 10; ++i) - *(phys_2_virt(global_CR3) + i) = 0UL; - */ - flush_tlb(); kinfo("Memory management unit initialize complete!"); @@ -347,4 +335,15 @@ unsigned long page_clean(struct Page *p) ++p->zone->count_pages_free; --p->zone->total_pages_link; } -} \ No newline at end of file +} + +/** + * @brief 释放连续number个内存页 + * + * @param page 第一个要被释放的页面的结构体 + * @param number 要释放的内存页数量 number<64 + */ +void free_pages(struct Page *page, int number) +{ + // @todo: 释放连续number个内存页 +} diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index 37babe87..3c8d7c46 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -30,7 +30,7 @@ // 虚拟地址与物理地址转换 #define virt_2_phys(addr) ((unsigned long)(addr)-PAGE_OFFSET) #define phys_2_virt(addr) ((unsigned long *)((unsigned long)(addr) + PAGE_OFFSET)) - +// 获取对应的页结构体 #define Virt_To_2M_Page(kaddr) (memory_management_struct.pages_struct + (virt_2_phys(kaddr) >> PAGE_2M_SHIFT)) #define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT)) @@ -219,7 +219,13 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags); */ unsigned long page_clean(struct Page *page); - +/** + * @brief 释放连续number个内存页 + * + * @param page 第一个要被释放的页面的结构体 + * @param number 要释放的内存页数量 number<64 + */ +void free_pages(struct Page *page, int number); /** * @brief 内存页表结构体 diff --git a/kernel/mm/slab.c b/kernel/mm/slab.c index 250e8847..2976f131 100644 --- a/kernel/mm/slab.c +++ b/kernel/mm/slab.c @@ -294,22 +294,21 @@ ul slab_free(struct slab *slab_pool, void *addr, ul arg) // 有对应的析构函数,调用析构函数 if (slab_pool->destructor != NULL) slab_pool->destructor((char *)slab_obj_ptr->vaddr + slab_pool->size * index, arg); - + // 当前内存对象池的正在使用的内存对象为0,且内存池的空闲对象大于当前对象池的2倍,则销毁当前对象池,以减轻系统内存压力 - if((slab_obj_ptr->count_using==0)&&((slab_pool->count_total_free>>1)>=slab_obj_ptr->count_free)) + if ((slab_obj_ptr->count_using == 0) && ((slab_pool->count_total_free >> 1) >= slab_obj_ptr->count_free)) { // 防止删除了slab_pool的cache_pool入口 - if(slab_pool->cache_pool==slab_obj_ptr) + if (slab_pool->cache_pool == slab_obj_ptr) slab_pool->cache_pool = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list); - + list_del(&slab_obj_ptr->list); slab_pool->count_total_free -= slab_obj_ptr->count_free; - + kfree(slab_obj_ptr->bmp); page_clean(slab_obj_ptr->page); - free_pages(slab_obj_ptr->page,1); + free_pages(slab_obj_ptr->page, 1); kfree(slab_obj_ptr); - } return 0; @@ -319,6 +318,89 @@ ul slab_free(struct slab *slab_pool, void *addr, ul arg) return ENOT_IN_SLAB; } +/** + * @brief 初始化内存池组 + * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间 + * @return ul + */ +ul slab_init() +{ + // 将slab的内存池空间放置在mms的后方 + ul tmp_addr = memory_management_struct.end_of_struct; + + for (int i = 0; i < 16; ++i) + { + // 将slab内存池对象的空间放置在mms的后面,并且预留4个unsigned long 的空间以防止内存越界 + kmalloc_cache_group[i].cache_pool = (struct slab_obj *)memory_management_struct.end_of_struct; + memory_management_struct.end_of_struct += sizeof(struct slab_obj) + (sizeof(ul) << 2); + + list_init(&(kmalloc_cache_group[i].cache_pool->list)); + + // 初始化内存池对象 + kmalloc_cache_group[i].cache_pool->count_using = 0; + kmalloc_cache_group[i].cache_pool->count_free = PAGE_2M_SIZE / kmalloc_cache_group[i].size; + kmalloc_cache_group[i].cache_pool->bmp_len = (((kmalloc_cache_group[i].cache_pool->count_free + sizeof(ul) * 8 - 1) >> 6) << 3); + kmalloc_cache_group[i].cache_pool->bmp_count = kmalloc_cache_group[i].cache_pool->count_free; + + // 在slab对象后方放置bmp + kmalloc_cache_group[i].cache_pool->bmp = (ul *)memory_management_struct.end_of_struct; + + // bmp后方预留4个unsigned long的空间防止内存越界,且按照8byte进行对齐 + memory_management_struct.end_of_struct += kmalloc_cache_group[i].cache_pool->bmp_len + ((sizeof(ul) << 2) & (~sizeof(ul) - 1)); + + memset(kmalloc_cache_group[i].cache_pool->bmp, 0, kmalloc_cache_group[i].cache_pool->bmp_len); + + kmalloc_cache_group[i].count_total_using = 0; + kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool->count_free; + /* + memset(kmalloc_cache_size[i].cache_pool->color_map,0xff,kmalloc_cache_size[i].cache_pool->color_length); + + for(j = 0;j < kmalloc_cache_size[i].cache_pool->color_count;j++) + *(kmalloc_cache_size[i].cache_pool->color_map + (j >> 6)) ^= 1UL << j % 64; + + kmalloc_cache_size[i].total_free = kmalloc_cache_size[i].cache_pool->color_count; + kmalloc_cache_size[i].total_using = 0; + */ + } + + struct Page *page = NULL; + + // 将上面初始化内存池组时,所占用的内存页进行初始化 + ul tmp_page_mms_end = virt_2_phys(memory_management_struct.end_of_struct >> PAGE_2M_SHIFT); + for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)); i < tmp_page_mms_end; ++i) + { + page = memory_management_struct.pages_struct + i; + + // 下面注释掉的这部分工作貌似在page_init()里面已经做了 + // 在mms的bmp中,置位对应的位 + //*(memory_management_struct.bmp + ((page->addr_phys>>PAGE_2M_SHIFT)>>6)) |= 1UL<<((page->addr_phys >> PAGE_2M_SHIFT)%64); + + //++(page->zone->count_pages_using); + //--(page->zone->count_pages_free); + + page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED); + } + + printk_color(ORANGE, BLACK, "2.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d\n", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free); + + // 为slab内存池对象分配内存空间 + ul *virt = NULL; + for (int i = 0; i < 16; ++i) + { + // 获取一个新的空页并添加到空页表,然后返回其虚拟地址 + virt = (ul*)(PAGE_2M_ALIGN(memory_management_struct.end_of_struct+PAGE_2M_SIZE*i)); + page = Virt_To_2M_Page(virt); + + page_init(page, PAGE_PGT_MAPPED|PAGE_KERNEL|PAGE_KERNEL_INIT); + + kmalloc_cache_group[i].cache_pool->page = page; + kmalloc_cache_group[i].cache_pool->vaddr = virt; + } + printk_color(ORANGE, BLACK, "3.memory_management_struct.bmp:%#018lx\tzone_struct->count_pages_using:%d\tzone_struct->count_pages_free:%d\n", *memory_management_struct.bmp, memory_management_struct.zones_struct->count_pages_using, memory_management_struct.zones_struct->count_pages_free); + + return 0; +} + /** * @brief 通用内存分配函数 * diff --git a/kernel/mm/slab.h b/kernel/mm/slab.h index 32a546e8..1328aaf0 100644 --- a/kernel/mm/slab.h +++ b/kernel/mm/slab.h @@ -12,7 +12,6 @@ #define ESLAB_NOTNULL 101 #define ENOT_IN_SLAB 102 - struct slab_obj { struct List *list; @@ -26,15 +25,15 @@ struct slab_obj void *vaddr; // 位图 - ul bmp_len; // 位图的长度(字节) - ul bmp_count; // 位图的有效位数 + ul bmp_len; // 位图的长度(字节) + ul bmp_count; // 位图的有效位数 ul *bmp; }; // slab内存池 struct slab { - ul size; + ul size; // 单位:byte ul count_total_using; ul count_total_free; // 内存池对象 @@ -58,11 +57,11 @@ void *kmalloc(unsigned long size, unsigned long flags); /** * @brief 通用内存释放函数 - * + * * @param address 要释放的内存地址 - * @return unsigned long + * @return unsigned long */ -unsigned long kfree(void * address); +unsigned long kfree(void *address); /** * @brief 创建一个内存池 @@ -79,26 +78,53 @@ struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), voi * @brief 销毁内存池对象 * 只有当slab对象是空的时候才能销毁 * @param slab_pool 要销毁的内存池对象 - * @return ul - * + * @return ul + * */ -ul slab_destroy(struct slab * slab_pool); +ul slab_destroy(struct slab *slab_pool); /** * @brief 分配SLAB内存池中的内存对象 - * + * * @param slab_pool slab内存池 * @param arg 传递给内存对象构造函数的参数 * @return void* 内存空间的虚拟地址 */ -void* slab_malloc(struct slab *slab_pool, ul arg); +void *slab_malloc(struct slab *slab_pool, ul arg); /** * @brief 回收slab内存池中的对象 - * + * * @param slab_pool 对应的内存池 * @param addr 内存对象的虚拟地址 * @param arg 传递给虚构函数的参数 - * @return ul + * @return ul */ -ul slab_free(struct slab* slab_pool, void* addr, ul arg); \ No newline at end of file +ul slab_free(struct slab *slab_pool, void *addr, ul arg); + +/** + * @brief 初始化内存池组 + * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间 + * @return ul + */ +ul slab_init(); + +struct slab kmalloc_cache_group[16] = + { + {32, 0, 0, NULL, NULL, NULL, NULL}, + {64, 0, 0, NULL, NULL, NULL, NULL}, + {128, 0, 0, NULL, NULL, NULL, NULL}, + {256, 0, 0, NULL, NULL, NULL, NULL}, + {512, 0, 0, NULL, NULL, NULL, NULL}, + {1024, 0, 0, NULL, NULL, NULL, NULL}, // 1KB + {2048, 0, 0, NULL, NULL, NULL, NULL}, + {4096, 0, 0, NULL, NULL, NULL, NULL}, // 4KB + {8192, 0, 0, NULL, NULL, NULL, NULL}, + {16384, 0, 0, NULL, NULL, NULL, NULL}, + {32768, 0, 0, NULL, NULL, NULL, NULL}, + {65536, 0, 0, NULL, NULL, NULL, NULL}, + {131072, 0, 0, NULL, NULL, NULL, NULL}, // 128KB + {262144, 0, 0, NULL, NULL, NULL, NULL}, + {524288, 0, 0, NULL, NULL, NULL, NULL}, + {1048576, 0, 0, NULL, NULL, NULL, NULL}, // 1MB +}; \ No newline at end of file