rCore-Tutorial-Book-v3 icon indicating copy to clipboard operation
rCore-Tutorial-Book-v3 copied to clipboard

rCore-Tutorial-Book-v3/chapter4/5kernel-app-spaces

Open utterances-bot opened this issue 4 years ago • 36 comments

内核与应用的地址空间 — rCore-Tutorial-Book-v3 0.1 文档

https://rcore-os.github.io/rCore-Tutorial-Book-v3/chapter4/5kernel-app-spaces.html

utterances-bot avatar May 05 '21 16:05 utterances-bot

你好,page_tables.rs中的 unmap方法中获取物理页帧的方法,可以由find_pte_create换成find_pte这个方法吗?然后根据Option进行逻辑的编写,我觉得如果是unmap的话,之前map过的虚拟页号在页表中已经建立了,只需找到物理页帧对应的页表项就行,create可以不用吗?

TroubleMaker369 avatar Jul 17 '21 07:07 TroubleMaker369

@TroubleMaker369 你说得对,这里的确应该调用find_pte而非find_pte_create,稍后修改。

wyfcyx avatar Jul 17 '21 08:07 wyfcyx

你好,在from_elf方法中max_end_vpn这个变量为什么是直接赋值,而不是每次都取max。是因为program header的vpn_range是严格递增的吗?

csyJoy avatar Nov 21 '21 09:11 csyJoy

页表项标志位没有相关的访问控制逻辑?还是有我没有了解到的机制?请指教

thlstsul avatar Dec 27 '21 09:12 thlstsul

而第 32 行的 from_elf 则可以应用的 ELF 格式可执行文件解析出各数据段并对应生成应用的地址空间

不太通顺

liangyongrui avatar Mar 14 '22 05:03 liangyongrui

有一点不太理解, 如果在MemorySet中用Vec来存储MapArea的话, sys_munmap的时候只能遍历这个Vec来找到对应的MapArea? 还是说后面的章节有进一步的优化设计呢?

itewqq avatar Mar 20 '22 17:03 itewqq

高于256G且低于0xffff_ffc0_0000_0000是不是不能被访问到,因为通不过mmu

Yui5427 avatar Apr 05 '22 15:04 Yui5427

高于256G且低于0xffff_ffc0_0000_0000是不是不能被访问到,因为通不过mmu

你的理解是对的。

wyfcyx avatar Apr 05 '22 16:04 wyfcyx

在user/src/linker.ld中如果忽略掉第28行*(.debug*),最后会有Panicked at src/mm/address.rs:202 start VPN:0x80a9f > end VPN:0x80800!的意外情况,请问大家这是为什么啊?

RobinWitch avatar Nov 23 '22 13:11 RobinWitch

@mxq-151 帮你删掉了。如果想自己删除的话,只需要找到当前节的issue页面就能删掉自己的评论了。

wyfcyx avatar Nov 26 '22 13:11 wyfcyx

@RobinWitch 这样的话会保留应用可执行文件中的调试信息,使得应用可执行文件大小膨胀,最终超出我们预设的物理内存大小限制。

wyfcyx avatar Nov 27 '22 04:11 wyfcyx

@RobinWitch 这样的话会保留应用可执行文件中的调试信息,使得应用可执行文件大小膨胀,最终超出我们预设的物理内存大小限制。

@wyfcyx 十分感谢!

RobinWitch avatar Dec 05 '22 15:12 RobinWitch

应用地址空间的布局的配图有误?0x0的位置是空指针

longguzzz avatar Dec 06 '22 10:12 longguzzz

因为在应用二进制镜像中,内存布局中各个逻辑段的置和访问限制等信息都被裁剪掉了。

这里的“置和访问限制”是“标志位和访问限制”吗?

longguzzz avatar Dec 06 '22 10:12 longguzzz

@longguzzz 应用地址空间配图稍后更新;“置和访问限制”应该是“位置和访问限制”。

wyfcyx avatar Dec 06 '22 23:12 wyfcyx

如果在trampoline后紧凑地放置Kernel Stack,则 App 0 Kernel Stack范围为左闭右开区间[2^64B-(4KiB+KERNEL_STACK_SIZE), 2^64B-4KiB) App i Kernel Stack范围为左闭右开区间[2^64B-(i+1)×(4KiB+KERNEL_STACK_SIZE), 2^64B-(i+1)×(4KiB+KERNEL_STACK_SIZE)+KERNEL_STACK_SIZE)

App Address Space(High)的图示中标注2^64B-i×(4KiB+KERNEL_STACK_SIZE)的地方实际上在App i-1的最低位置。

longguzzz avatar Dec 12 '22 09:12 longguzzz

@longguzzz 地址空间配图已更新。

wyfcyx avatar Dec 12 '22 16:12 wyfcyx

有个问题需要请教:跳板的虚拟地址为VirtAddr::from(TRAMPOLINE),而TRAMPOLINE为usize::MAX - PAGE_SIZE + 1,但这个地址值已经超越了SV39分页模式的最大合法虚拟地址2^39,甚至也超越了最大合法物理地址2^56,因此应该已经不合法了吧?

ljsheng7128 avatar Apr 11 '23 08:04 ljsheng7128

你好,在from_elf方法中max_end_vpn这个变量为什么是直接赋值,而不是每次都取max。是因为program header的vpn_range是严格递增的吗?

可以解答一下这个问题吗,我对max_end_vpn的获取这一点也非常困惑。

Unik-lif avatar May 03 '23 08:05 Unik-lif

可以解答一下这个问题吗,我对max_end_vpn的获取这一点也非常困惑。

哦,我找到资料了qaq,求夸!

PT_LOAD Specifies a loadable segment, described by p_filesz and p_memsz. The bytes from the file are mapped to the beginning of the memory segment. If the segment's memory size (p_memsz) is larger than the file size (p_filesz), the extra bytes are defined to hold the value 0 and to follow the segment's initialized area. The file size can not be larger than the memory size. Loadable segment entries in the program header table appear in ascending order, sorted on the p_vaddr member.

https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html

这里提到PT_LOAD类型的代码段是根据p_vaddr来排布的,所以就能解释上面代码关于max_end_vpn的写法了。

Unik-lif avatar May 03 '23 09:05 Unik-lif

你好,unmap或unmap_one后需要当页表节点的所有页表项都是invalid时执行page_table.frames.remove()回收页表中相关页表节点物理页帧以及祖先物理页帧的空间吗?我通过grep没有找到相关代码,是某些地方隐含地执行了相关操作吗?还是目前不需要回收呢?也可能我还没理解到位。

VisualMike-I avatar May 06 '23 02:05 VisualMike-I

MapArea::new时会start_va.floor(), end_va.ceil(),那么应用链接脚本中不是所有段都页对齐那么构建应用地址空间时有些段数据是否有重叠(两个MapArea段含有同一虚拟页面,如.data和.bss段)?

VisualMike-I avatar May 06 '23 09:05 VisualMike-I

@VisualMike-I 是的,可能会产生冲突甚至后加入的段覆写先加入的段的情况,因此目前无论内核还是应用,段与段之间都插入强制4K页对齐。

wyfcyx avatar May 06 '23 17:05 wyfcyx

@VisualMike-I 在MapArea::unmap_one中,self.data_frames.remove(&vpn);其实是删除了一个键值对(注意这是一个map),因此作为值的FrameTracker同时也被删掉了,此时触发了FrameTracker::drop将这个物理页回收。

wyfcyx avatar May 06 '23 17:05 wyfcyx

@wyfcyx 嗯嗯这么晚了感谢抽出宝贵的时间回答,懂了。谢谢,以下是纯建议,有些啰嗦,没时间看不用回复。 数据所在的物理页帧FrameTracker被drop回收了,但是页表项所在的物理页帧以及祖先页表节点所在物理页帧好像没根据其他页表项是非为空而drop回收掉。 data_frames.remove()回收了应用实际数据所在的物理页帧,但没有考虑页表节点所在的物理页帧回收问题,另外page_table.unmap()中也没有考虑回收页表节点所在的物理页帧回收问题,只是将虚拟页号对应页表项所在64位比特清零。按道理是否应该当某一页表节点的页表项全为invalid时回收当前页表节点所在物理页帧的空间,进而还要考虑祖先页表节点的物理页帧回收。 虽然os运行结束后各变量生命周期结束会drop回收掉页表节点所在物理页帧的空间,但在目前的实现中,若是在os运行期间执行unmap操作,不会回收页表节点所在物理页帧空间。尽管目前的实现没有上层应用真正触发unmap操作,但从功能完备性上是否应考虑释放页表节点所在物理页帧的空间?经过一定的算法在合适的地方调用page_table.frames.remove(a_frame_tracker)。但现在是vec向量存储frame_tracker,貌似不好根据ppn查找frame_tracker,需要遍历吗?BTreeMap应该好找,时间效率高。 (2023.9.30更新: 页表的物理页帧下一章提及了何时清理。)

另外在ch4 user/src/linker.ld 中,.data和.bss段之间好像没有页对齐,尽管它们访问权限相同,但是它们是由两个独立的program header标识的,那么根据代码会创建两个MapArea,可能导致覆盖。

🌹

VisualMike-I avatar May 07 '23 03:05 VisualMike-I

@VisualMike-I

  1. 关于保存页表的物理页,由于数量很少(只有保存数据的1/512),目前没有设计支持分配之后运行时动态回收的功能,而是进程退出时一起回收的。要支持这个机制的话,得维护页表树结构的引用计数才行,还要考虑如何高效利用内存。
  2. 没注意到.data.bss之间没有页对齐,那么MapArea确实有可能覆盖,好在不影响功能吧,也不是严重问题。后面加上页对齐也可。

wyfcyx avatar May 08 '23 15:05 wyfcyx

请问MapArea中的pub fn copy_data(&mut self, page_table: &mut PageTable, data: &[u8])函数为什么一定需要page_table这个参数,按理说我们完全可以通过MapArea中的data_frames来完成同样的事情啊,比如我这么写:

pub fn copy_data(&mut self, _page_table: &mut PageTable, data: &[u8]) {
        assert_eq!(self.map_type, MapType::Framed);
        let mut start: usize = 0;
        let mut current_vpn = self.vpn_range.get_start();
        let len = data.len();
        loop {
            let src = &data[start..len.min(start + PAGE_SIZE)];
            /*
            let dst = &mut page_table
                .translate(current_vpn)
                .unwrap()
                .ppn()
                .get_bytes_array()[..src.len()];
            */
            let dst = &mut self.data_frames
                .get(&current_vpn)
                .unwrap()
                .ppn
                .get_bytes_array()[..src.len()];
            dst.copy_from_slice(src);
            start += PAGE_SIZE;
            if start >= len {
                break;
            }
            current_vpn.step();
        }
    }

有什么区别吗

xuanz20 avatar Aug 25 '23 12:08 xuanz20

四个逻辑段.text/.rodata/.data/.bss被恒等映射到物理内存,这使得我们在无需调整内核内存布局 os/src/linker.ld的情况下就仍能和启用页表机制之前那样访问内核的各数据段。

请问这里无需调整内核内存布局仍能像之前那样访问内核各数据段是什么意思呢? linker.ld链接时候的地址应该也都是虚拟地址我的理解?只要QEMU加载的时候把内核加载到0x80200000就可以了吧

xuanz20 avatar Aug 25 '23 13:08 xuanz20

勘误病句:

实现 push 方法地址空间中插入一个逻辑段 MapArea 的时候

改成“在push方法中实现地址空间中插入一个逻辑段MapArea时”

chestNutLsj avatar Sep 26 '23 06:09 chestNutLsj

@chestNutLsj 多谢您近期提出的大量反馈意见。最近工作比较忙,等后面有空了会集中修一下。

wyfcyx avatar Sep 26 '23 07:09 wyfcyx