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

rCore-Tutorial-Book-v3/chapter2/3batch-system

Open utterances-bot opened this issue 3 years ago • 18 comments

实现批处理操作系统 — rCore-Tutorial-Book-v3 0.1 文档

https://rcore-os.github.io/rCore-Tutorial-Book-v3/chapter2/3batch-system.html

utterances-bot avatar Mar 14 '21 01:03 utterances-bot

关于fence.i还有疑问, 它是清空i cache的. 我的问题是, 代码中修改的内存是0x80400000, 但这个内存原本也没有存指令, 之前取指也不会从那里取, 这片内存不会进入i-cache. 我哪里错了呢?

Tokubara avatar Mar 14 '21 01:03 Tokubara

@Tokubara 在执行第一个应用之前清空icache确实没用,因为那个时候icache里面还没有相关内容。但是在执行后面应用的时候,icache里面就会缓存上一个应用的指令,因此需要手动清空它。

wyfcyx avatar Mar 14 '21 05:03 wyfcyx

@wyfcyx 我有个很困惑的点是为啥我们要在应用程序的链接文件中设置0x80400000地址呢?之后在内核程序中我们是自己写代码手动去把应用程序从数据段copy到以 0x80400000 开头的位置的啊,按很自然的理解来说,copy之后只要把指令寄存器指向0x80400000,做一些初始化工作就应该可以运行了啊。我不明白的是为啥应用程序的链接文件中要指定0x80400000地址,明明内核中就手动copy到了这个地址,看起来这个设定没什么用啊,但不设定又会报错。

按我自己的理解,我不在应用程序链接文件中设置BASE_ADDRESS,我只要保证应用程序入口点_start 的第一条指令在生成的bin文件的最前面,当我内核手动写代码copy 这个应用程序bin文件到0x80400000之后就应该能运行

不知道我理解是有什么问题? 为什么我们在应用程序链接文件中不设置0x80400000会报错?

还有内核程序加载到内存我也一样很不理解为啥要在链接文件中设置BASE_ADDRESS, 因为我们的qemu命令中已经设置了啊,很困惑

dunmengjun avatar Jul 19 '21 06:07 dunmengjun

@dunmengjun 因为目前我们生成的二进制文件并不是位置无关的,其中可能会存在一些绝对地址,这些绝对地址当且仅当程序被加载到内存中正确的位置时才是合法的。由于我们在内核中已经固定了程序被加载到的位置,所以程序自身也必须在编译时将起始地址设为同一个值,这样那些绝对的地址才能指向正确的代码和数据。

当然我们也许可以将二进制文件生成为位置无关的,但是内核在加载的时候根据其实际加载的位置可能需要对二进制文件中的某些符号进行动态重定位,这大概需要更加完善的二进制文件解析和修改功能,对于我们教学内核来说完全没有必要。目前这种直接拷贝的方法还是比较简单且恰当的。

从第四章开始我们就支持ELF加载了,在页表机制的帮助下,它能够支持任意的应用地址空间布局(包括rust默认的布局)。然而我们出于内存管理的方便仍然自定义了应用的地址空间布局。这些都可以看成内核功能所限因而不得不做出的取舍。

wyfcyx avatar Jul 19 '21 09:07 wyfcyx

@wyfcyx 我理解了,谢谢您,您解释的很清晰。 还有一个很小的问题是,为什么二进制文件会有这样的设计呢?为什么需要绝对地址,是有什么case需要这样做吗? 有这个问题是因为我其实没太理解在程序加载这样的场景中,绝对地址有啥好处。感觉我自己这方面的知识有点缺乏了,您有没有什么推荐的文档给我读读?有中文最好,英文也可。 再次感谢您😊

后记:我在后面的章节中看到了解释 https://nju-projectn.github.io/ics-pa-gitbook/ics2020/4.2.html, 谢谢

dunmengjun avatar Jul 19 '21 09:07 dunmengjun

error: Could not find incbin file '/../target/riscv64gc-unknown-none-elf/release/03priv_inst.bin'
   |
note: instantiated into assembly here
  --> <inline asm>:39:13

最后生成的时候地址文件是对的,但是报错无法链接

PeterWrighten avatar Jan 28 '22 12:01 PeterWrighten

@PeterWrighten 应该是../user/target

wyfcyx avatar Jan 28 '22 12:01 wyfcyx

@PeterWrighten 应该是../user/target

我改了地址了,可是依旧编译不过。文件就在那个目录里,我是之前把这个重构为cargo工作空间的那个。重构后bin二进制文件生成在根目录的target里。

PeterWrighten avatar Jan 28 '22 16:01 PeterWrighten

请问一下,这个fence.i指令清除指令缓存后会立即重新从内存中读入指令缓存块吗?如果是的话,那是不是应该将fence.i指令放到load_app函数末尾?

CtrlZ233 avatar May 22 '22 01:05 CtrlZ233

请问一下,这个fence.i指令清除指令缓存后会立即重新从内存中读入指令缓存块吗?如果是的话,那是不是应该将fence.i指令放到load_app函数末尾?

@CtrlZ233 这个问题还是蛮有意思的,我们可以开一个issue讨论一下。

wyfcyx avatar May 22 '22 04:05 wyfcyx

首先 new 被声明为一个 unsafe 函数,是因为我们希望使用者在创建一个 UPSafeCell 的时候保证在访问 UPSafeCell 内包裹的数据的时候始终不违背上述模式:即访问之前调用 exclusive_access ,访问之后销毁借用标记再进行下一次访问。这只能依靠使用者自己来保证,但我们提供了一个保底措施:当使用者违背了上述模式,比如访问之后忘记销毁就开启下一次访问时,程序会 panic 并退出。

或是是我理解有误,但是不是就算不将new函数声明为unsafe,仅仅是exclusive_access的实现就确保了,若引用未销毁就开启下一次访问,便会导致panic的功能(因为对refCell来说,只能同时允许一个borrow_mut引用,而我们只允许了外部使用borrow_mut来访问inner实例)。

DevRickLin avatar Jun 05 '22 12:06 DevRickLin

首先 new 被声明为一个 unsafe 函数,是因为我们希望使用者在创建一个 UPSafeCell 的时候保证在访问 UPSafeCell 内包裹的数据的时候始终不违背上述模式:即访问之前调用 exclusive_access ,访问之后销毁借用标记再进行下一次访问。这只能依靠使用者自己来保证,但我们提供了一个保底措施:当使用者违背了上述模式,比如访问之后忘记销毁就开启下一次访问时,程序会 panic 并退出。

或是是我理解有误,但是不是就算不将new函数声明为unsafe,仅仅是exclusive_access的实现就确保了,若引用未销毁就开启下一次访问,便会导致panic的功能(因为对refCell来说,只能同时允许一个borrow_mut引用,而我们只允许了外部使用borrow_mut来访问inner实例)。

@DevRickLin 如果在单线程上基于RefCell的确可以确保安全性。但是现在UPSafeCell是用来包裹可能被多线程并发访问的数据结构,而RefCell并不是线程安全的,也即并没有实现Sync Trait。因此这里的unsafe是需要调用者保证以线程安全的方式使用UPSafeCell:也即在获取与释放操作的中间不能进行执行流(或称线程)的切换。

wyfcyx avatar Jun 05 '22 15:06 wyfcyx

虽然用rust确实比C更加现代化,但是边学rust边学操作系统的感觉真的太酸爽了。。。

silverbulletmdc avatar Apr 04 '23 03:04 silverbulletmdc

有个问题,就是use std::cell::RefCell; static A: RefCell = RefCell::new(3);这个std是标准库,应该不能用吧,我现在引用RefCell,是core库的

lgwmf avatar May 18 '23 01:05 lgwmf

.quad 和.space 是riscv提供的指令,还是汇编器指令啊

yimuu avatar Apr 23 '24 13:04 yimuu