-
-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
新的内存管理模块 #301
新的内存管理模块 #301
Conversation
* 添加bump分配器 * 修改BumpAllocator的分配逻辑 * bugfix:bump分配器的分配逻辑修改 * 调整注释格式并删除无用操作
* 新版内存管理的Arch部分。(尚未完成x8664的初始化部分) * 页表、页表项的抽象 * 将内存分配器移动到mm/allocator文件夹下
* new: PageMapper and PageFlush
* 新增kernel mapper,以及从multi boot2获取内存信息 * reformat
* 添加slab分配器
修改printk,使得kdebug等宏,不会进行堆内存分配。
* 新增VFS文档,以及修改文档配置 (#209) * 1.新增vfs设计文档 2.修改文档版权标志为"2022-2023, DragonOS Community" 3.修改电脑版文档页面的宽度为90% * layout.html末尾加空行 * 修正了FAT32判断逻辑,解决了文件系统为FAT12/16时系统无法正常启动的问题。 (#211) * fix(fat): fix determination of fat type casue crash if fs is fat12/16 * refactor(fat): split BiosParameterBlock.validate() into BiosParameterBlockFAT32.validate() and BiosParameterBlockLegacy.validate() * 调整“最大允许的簇号”的常量放置的位置。 * 增加x87FPU支持 (#212) * remove `ret_from_syscall` *修复ps2键盘驱动程序inode在进程fork的时候导致死锁的问题. *更新: VFS每次拷贝文件描述符的时候,都会去调用inode的open函数 * 部分函数从返回值为Result<<>,i32>修改为Result<<>,SystemError> (#210) * 将Result<<>,i32>替换为Result<<>,SystemError> * bugfix: 显示双缓冲区初始化的时候,连续注册了两次Video Softirq的问题。 * 第一套键盘扫描码的状态机 (#216) 第一套键盘扫描码的状态机 * 将TTY与stdio进行连接,实现基本的stdio功能 (#217) * 将stdio与tty接上 * Patch keyboard capslock alt (#219) * keyboard-alt-capslock * 解决键盘输入'%'字符的时候无法回显的bug * Add dup,dup2 (#224) * dup,dup2 * fix: sys_dup2语义与posix不一致的问题 * 添加了qemu使用VNC作为图像输出的选项 (#222) * 添加了qemu使用VNC作为图像输出的选项 * 设置vnc端口为5900 * 软中断&定时器重构 (#223) * 软中断&定时器重构 * 修改timer的clock() * 删除debug信息 * V0.1.6发行日志&更新构建系统文档 (#225) 1.更新构建系统文档 2.V0.1.6发行日志 * Patch add 0.1.6 changelog (#226) * 修正标题错误 * 修复显示刷新线程的空指针问题 (#228) * 新增设备驱动模型,为设备和驱动提供高层视图 (#227) * 添加base mod * 添加设备驱动模型相关文件 * 删除单独的mod文件,使用mod.rs,修改一些格式上的问题 * 移动驱动错误类型到该文件 * 修改一些格式上的问题 * 修改CFSqueue从Vec变成红黑树 (#229) 使用了由tickbh编写的rbtree: https://github.com/tickbh/rbtree-rs/blob/master/src/lib.rs * new: lazy_init (#230) * Patch add lazy init (#236) * 修正并发安全问题 * pci重构+pcie支持 (#235) * pci重构+pcie支持 * pci重构测试完成 * 修正makefile的问题 * 小修改 * 修改函数名字 * 增加对dhcpv4的支持(tcp、udp socket已写好,但由于缺少epoll机制,尚未完整测试) (#237) * 为virtio网卡完成smoltcp的phy层配置 * raw socket * 初步写完udp和tcp socket * 能够正常通过dhcp获取ipv4地址(具有全局iface btree) * 调整brk系统调用,使得参数、返回值与Linux一致 (#238) * 新增用于测试relibc的app * 为适配relibc,修改do_execve中关于用户栈的内容的设置 * 调整brk系统调用,使得参数、返回值与Linux一致 * 修改errno,使其与relibc的保持一致 (#234) 修改errno,使其与relibc的保持一致 * 修复ecam无法获取MCFG table的问题 (#241) * 修复Issue#220;vnc的端口号恢复5900 (#243) * 修复Issue#220 * qemu-vnc端口号恢复为5900 * new: DowncastArc and its docs (#244) * 增加定时器和软中断文档,修改了softirq面向c的接口 (#245) * 增加定时器和软中断文档 * 修改softirq对c的接口和文档 * 修改文档格式 * 新增网络socket的系统调用接口 (#247) 1.修复spinlock忘记恢复rflags的问题 2.WaitQueue增加wakeup_all的功能 3.完善tcp,udp,raw socket 4.把PollStatus结构体改为使用bitflags 5.新增iovec结构体 6.完成网络的系统调用 7.在bootstrap里面添加dnsmasq bridge-utils iptables * 新增SysFS (#250) * 添加sysfs * 注册sysfs * 添加sysfs相关 * 添加rust-anlyzer辅助配置 * 将设备与sysfs相关联 * 添加单独的文件管理sysfs下的文件夹 * 解决使用zsh在构建DragonOS时,无法直接使用一键初始化脚本进行安装的问题 (#252) * 匿名管道重构&增加IrqArch trait以及IrqFlags及其守卫 (#253) * 实现匿名管道 * 增加IrqArch trait以及IrqFlags及其守卫 * 根据sysfs完善设备驱动模型 & 添加sysfs官方文档 (#254) * 根据sysfs完善设备驱动模型 * 添加sysfs官方文档 * doc: V0.1.7发行日志 (#255)
* 完成vma的代码编写(尚未实现匿名页反向映射) * 添加创建页表的函数
* 完成ELF加载器的代码 * reformat
* 重写execve系统调用 * reformat code
* 添加bump分配器 * 修改BumpAllocator的分配逻辑 * bugfix:bump分配器的分配逻辑修改 * 调整注释格式并删除无用操作 * 初始化伙伴分配器 * 抽离共有方法,修改逻辑 * 格式化代码 * 完善初始化分配器的逻辑,如果内存足够大可能占用多个页来存储 * 完善分配器的分配释放逻辑 * 解决无法通过编译的问题 * 修复边界值带来的bug * 添加slab分配器 * 减小buddy结构体的占用空间 * bugfix:修改数据类型 * 找回buddy测试误删内容 * 测试伙伴算法 * 抽象出函数,修复entry的地址计算bug * buddy 分配器实现Allocator trait,同时加锁 * 移除无用测试代码 * 格式化代码 * 1.修改buddy,使得其能正常申请、释放页。 2.buddy改为从链表页首部申请内存 3.删除预留页计算器(因为发现不需要了) --------- Co-authored-by: longjin <[email protected]>
* 初始化的时候,把所有内存映射到页表。 * kernel mapper能正常运行,可以初始化textui * 设置全局分配器,并导出到C的kmalloc、kzalloc接口。(存在bug: acpi create mmio之后出错) * 1、解决由于locak_irq_save、local_irq_restore函数的汇编不规范导致影响栈行为的bug。 2、对mmio模块进行改动,使得能够正常运行。(存在问题:a. 缺乏统一的,已分配地址空间的管理机制。 b. 目前由于数据缺失,因此未归还空间到池中) 这个模块需要接下来进行优化、部分重构,但目前能跑。 3、目前能正常初始化到acpi模块
* 1、使得smp和apic能正常初始化。 2、增加LowAddressRemapping管理 * 能够进入pid=1的内核线程 * 能初始化virtio * 卡在了网卡初始化这里。 * pci的dma内存设置pwt和pcd * 解决KernelAllocator里面把不可变引用转为可变指针导致的未定义行为。 * 能进用户程序,显示调用sys_sbrk * 能够执行about应用程序(存在bug:随机双重加锁、map ananymous出错(随机性,重启就好))
* 1、使得smp和apic能正常初始化。 2、增加LowAddressRemapping管理 * 能够进入pid=1的内核线程 * 能初始化virtio * 卡在了网卡初始化这里。 * pci的dma内存设置pwt和pcd * 解决KernelAllocator里面把不可变引用转为可变指针导致的未定义行为。 * 能进用户程序,显示调用sys_sbrk * 能够执行about应用程序(存在bug:随机双重加锁、map ananymous出错(随机性,重启就好)) * gdb 调试rust内核 * 1.修复PageFlushAll在drop时没有刷新TLB的问题 2.修复buddy的一些内存越界问题(把paddr当成vaddr来用了) 3.调整:buddy free在迁移伙伴块后,把原来的entry位置清空. 4.elf load_elf_segment的时候,对要读取的文件的位置/大小进行了调整(有bug:about app无法运行,在malloc_query_free_chunk_bf函数里面报#GP)
1.修正rwLock未修改锁持有计数的bug 2.修复PageMapper::create未清空页表的问题 3.解决x86_64不支持XD时,页表项填写错误的问题 4.调整elf加载器,使得能够正确的加载relibc的程序
1. 删除调试日志 2. bugfix: 修复sys_gettimeofday对timezone参数的处理的bug 3. 删除无用的c文件 4. 编写文档
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
对于全局变量的修改是unsafe的,但内存模块里面不可避免地会使用到全局变量,所以有没有可能为全局变量封装函数,把unsafe块限制在对全局变量的改变上,而不外扩影响其他变量的检查。
} | ||
|
||
/// 从空闲链表的开头,取出1个指定阶数的伙伴块,如果没有,则返回None | ||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个文件的注释风格怎么不太一样
return self.0 * MMArch::PAGE_SIZE; | ||
} | ||
|
||
/// 将字节数转换为页帧数量 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个函数注释不太规范
|
||
/// 映射一段物理地址到指定的虚拟地址。 | ||
/// | ||
/// ## 参数 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里注释风格又突变了哈哈
@@ -1,7 +1,5 @@ | |||
#pragma once | |||
#include "mm.h" | |||
|
|||
extern void mmio_buddy_init(); | |||
extern void mmio_create(); | |||
extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
为什么不直接在头文件中声明函数,而是在文件中声明完了再在头文件中使用extern
|
||
/// 判断当前页表的第i个页表项是否已经填写了值 | ||
/// | ||
/// ## 参数 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里注释风格也不统一
|
||
/// 内核的第一个页表在pml4中的索引 | ||
/// 顶级页表的[256, 512)项是内核的页表 | ||
static KERNEL_PML4E_NO: usize = (X86_64MMArch::PHYS_OFFSET & ((1 << 48) - 1)) >> 39; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
一个模块的全局变量有没有可能做成一个结构体,每个全局变量是一个成员,方便管理。
这玩意不行,因为这结构体恰恰是利用了它“没有成员变量”的特点,才能够被到处直接使用(不然过不了rust借用检查器的,这是主要原因)。(外面的MMArch代指的就是X86_64MMArch)
要全局变量的另一个原因,是因为它被初始化的时候,没有动态内存分配(先有鸡先有蛋的问题)
…---原始邮件---
发件人: ***@***.***>
发送时间: 2023年7月22日(周六) 凌晨0:08
收件人: ***@***.***>;
抄送: ***@***.******@***.***>;
主题: Re: [DragonOS-Community/DragonOS] 新的内存管理模块 (PR #301)
@YJwu2023 commented on this pull request.
In kernel/src/arch/x86_64/mm/mod.rs:
> - let pml4t = unsafe { read_volatile(&next_pcb.mm.as_ref().unwrap().pgd) }; +pub type PageMapper = + crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>; + +/// @brief 用于存储物理内存区域的数组 +static mut PHYS_MEMORY_AREAS: [PhysMemoryArea; 512] = [PhysMemoryArea { + base: PhysAddr::new(0), + size: 0, +}; 512]; + +/// 初始的CR3寄存器的值,用于内存管理初始化时,创建的第一个内核页表的位置 +static mut INITIAL_CR3_VALUE: PhysAddr = PhysAddr::new(0); + +/// 内核的第一个页表在pml4中的索引 +/// 顶级页表的[256, 512)项是内核的页表 +static KERNEL_PML4E_NO: usize = (X86_64MMArch::PHYS_OFFSET & ((1 << 48) - 1)) >> 39;
一个模块的全局变量有没有可能做成一个结构体,每个全局变量是一个成员,方便管理。
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
注释的问题是,最开始我们用的
@brief 格式的,不符合rust官方规范(写成markdown),后来发现写成官方规范的md,自动补全提示的时候看注释比较美观。
那几个全局变量只有在初始化内存管理的时候需要用到,因此不影响。只有内存管理模块初始化的时候才操作了他们。后面都没影响了。
extern的原因是这函数不是在c里面实现的,所以extern呀哈哈哈,不然用到可能报错。
…---原始邮件---
发件人: ***@***.***>
发送时间: 2023年7月21日(周五) 晚上11:34
收件人: ***@***.***>;
抄送: ***@***.******@***.***>;
主题: Re: [DragonOS-Community/DragonOS] 新的内存管理模块 (PR #301)
@YJwu2023 commented on this pull request.
对于全局变量的修改是unsafe的,但内存模块里面不可避免地会使用到全局变量,所以有没有可能为全局变量封装函数,把unsafe块限制在对全局变量的改变上,而不外扩影响其他变量的检查。
In kernel/src/mm/allocator/buddy.rs:
> + /// 从order转换为free_area的下标 + /// + /// # 参数 + /// + /// - `order` - order + /// + /// # 返回值 + /// + /// free_area的下标 + #[inline] + fn order2index(order: u8) -> usize { + (order as usize - MIN_ORDER) as usize + } + + /// 从空闲链表的开头,取出1个指定阶数的伙伴块,如果没有,则返回None + ///
这个文件的注释风格怎么不太一样
In kernel/src/mm/allocator/page_frame.rs:
> +impl PageFrameCount { + // @brief 初始化PageFrameCount + pub const fn new(count: usize) -> Self { + return Self(count); + } + // @brief 获取页帧数量 + pub fn data(&self) -> usize { + return self.0; + } + + /// 计算这一段页帧占用的字节数 + pub fn bytes(&self) -> usize { + return self.0 * MMArch::PAGE_SIZE; + } + + /// 将字节数转换为页帧数量
这个函数注释不太规范
In kernel/src/mm/kernel_mapper.rs:
> + if self.readonly { + return None; + } else { + return Some(&mut self.mapper); + } + } + + /// @brief 获取内核映射器的page mapper的不可变引用 + #[inline(always)] + pub fn as_ref(&self) -> &PageMapper { + return &self.mapper; + } + + /// 映射一段物理地址到指定的虚拟地址。 + /// + /// ## 参数
这里注释风格又突变了哈哈
In kernel/src/mm/mmio.h:
> @@ -1,7 +1,5 @@ #pragma once #include "mm.h" -extern void mmio_buddy_init(); -extern void mmio_create(); +extern void mmio_create(uint32_t size, uint64_t vm_flagsu, uint64_t* res_vaddr, uint64_t* res_length);
为什么不直接在头文件中声明函数,而是在文件中声明完了再在头文件中使用extern
In kernel/src/mm/page.rs:
> + /// 获取当前页表的第i个页表项 + pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> { + let entry_virt = self.entry_virt(i)?; + return Some(PageEntry::new(Arch::read::<usize>(entry_virt))); + } + + /// 设置当前页表的第i个页表项 + pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> { + let entry_virt = self.entry_virt(i)?; + Arch::write::<usize>(entry_virt, entry.data()); + return Some(()); + } + + /// 判断当前页表的第i个页表项是否已经填写了值 + /// + /// ## 参数
这里注释风格也不统一
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
This reverts commit d8ad0a5.
实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。
内存管理模块主要由以下类型的组件组成:
除上面的新增内容以外,其它的更改内容: