当前位置: 首页 > article >正文

RISC-V Non-MMU Linux学习笔记

资料来源:
https://tinylab.org/riscv-non-mmu-linux-part1/#:~:text=MMU%20%E6%98%AF%E7%8E%B0%E4%BB%A3%E5%A4%84%E7%90%86%E5%99%A8
https://www.kernel.org/doc/Documentation/nommu-mmap.txt

MMU 是现代处理器中一个非常重要的硬件特性,主要用于虚拟地址与物理地址之间的转换。RISC-V 下可以通过设置 SATP 寄存器为 0 来彻底关闭 MMU。关掉 MMU 以后,所有的程序将共享同一片物理地址,而不再是“独占”一大片连续的虚拟地址空间,因此内核和应用的行为方式都将受到很大的影响。另外,在 RISC-V Linux 下,关闭 MMU 以后,内核和应用都将工作在纯 Machine Mode 模式,原有的 Machine Mode 的 Firmware 也不再需要,所以,这里也涉及到整个软件架构的变化,从原有的 M/S/U 三层权限变成更为扁平的 M/U 两层权限。

这篇博客中分析了 MMU 关闭后将影响哪些功能。PAGE_OFFSET = 0x80000000,不再需要 SBI Firmware,binfmt 的格式仅支持 binfmt flat,而不再支持 ELF等。

由于 ELF 格式依赖 MMU,所以禁用 MMU 以后的内核需要专门启用另外一种名为 FLAT 的程序格式,否则将无法正确地执行应用程序。这种格式来自 uClibc — 一种专门为嵌入式 Linux 系统设计的 C 库。在6.10版本的linux kernel上支持了FDPIC ELF格式,是ELF的一个变种,允许在没有MMU的系统上运行位置无关代码(PIC)。它在内部实现上与标准的ELF格式有所不同,特别是在程序链接表(PLT)的实现上,但对程序员来说,从外部来看,它仍然是一个ELF文件。FDPIC ELF格式支持动态加载和共享库的创建与维护,这在FLAT格式中是不支持的。
在这里插入图片描述
uClibc 支持 FLAT 的方式比较特殊,它并没有试图开发一系列完整的工具来支持 FLAT 格式,而是开发了一个转换工具 elf2flt。这个工具一般不独立使用,而是安装进其他工具链的目录结构中,以某种巧妙的方式去调整链接器的工作过程,进而最终产生 FLAT 格式的可执行文件。目前最好的使用 elf2flt 的方式是,直接用 Buildroot 构建一个完整的已经自动编译并安装好了 elf2flt 的 uClibc 工具链。要获得该工具链,仅需要在编译 Buildroot 时,同样禁用 MMU 即可。

一个nommu系统没有虚拟地址,任何“映射”只是跟踪分配了什么物理内存。对nommu的分配必须找到物理内存的连续区域,将其设置为零,并返回指向它开头的指针。这意味着如果malloc()找不到足够大的连续内存块,它将返回NULL。所有程序文本都必须是可重定位的:所以我们不能使用标准的ELF二进制文件。nommu要求在编译时指定显式堆栈大小,因为nommu系统无法自动增加堆栈(没有“保护页面”错误)。这些堆栈应该尽可能小,因为整个大小是在程序启动时分配的(需要连续的不可共享分配),如果系统无法获取该内存,则exec失败。默认大小(8k)基本上是内核堆栈。兆字节堆栈的标准Linux假设不适合用于nommu系统。

内核对无mmu条件下的内存映射的支持有限,例如在uClinux环境。从用户空间的角度来看,内存映射与mmap()系统调用、shmat()调用和execve()系统调用一起使用。从内核的角度来看,execve()映射实际上是由binfmt驱动程序执行的,它回调到mmap()例程来完成实际的工作。内存映射行为还影响fork(), vfork(), clone()和ptrace()的工作方式。在uClinux下,没有fork(), clone()必须提供CLONE_VM标志(子进程与父进程运行于相同的内存空间)。

匿名映射,MAP_PRIVATE:
在MMU的情况下:使用虚拟页,虚拟页可以映射到任意的物理页;在fork()中copy-on-write;
在无MMU的情况下:虚拟区域只能是连续页。
匿名映射,MAP_SHARED:
在MMU的情况下:除了没有CLONE_VM,其余与MAP_PRIVATE类似;
在无MMU的情况下:与MAP_PRIVATE一致。
文件,MAP_PRIVATE, PROT_READ / pro_exec, !PROT_WRITE:
在MMU的情况下:使用虚拟页读入文件,对文件的改变反映到内存中,fork时复制;
在无MMU的情况下:重用文件映射;写文件不影响映射;对内存中映射的写入其他进程可见,但不应该发生。
文件, MAP_PRIVATE, PROT_READ / PROT_EXEC, PROT_WRITE
在MMU的情况下:在写实际发生前被复制;写操作不映射到内存中,而是由swap支持;
在无MMU的情况下:与!PROT_WRITE相似,除了获得副本而不是共享。


http://www.kler.cn/a/301228.html

相关文章:

  • 独立站干货:WordPress主机推荐
  • 《探索 C++:一门强大且多功能的编程语言》
  • 【gitlab】gitlabrunner部署
  • VMware 中 虚拟机【Linux系统】固定 ip 访问
  • 深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度
  • 图像基础算法学习笔记
  • 视频安防监控LntonAIServer安防管理平台抖动检测和过亮过暗检测
  • 机器学习与深度学习的区别
  • 生命周期函数
  • vue elementUI更改Checkbox 多选框禁用状态下文本颜色
  • AutoSar AP平台的SOMEIP文档的理解笔记
  • C++ priority_queue
  • 漫谈设计模式 [4]:原型模式
  • go-map系统学习
  • livox mid360不使用ros接收雷达数据
  • StreamPark集成k8s运行Flink
  • busybox移植:全能脚本版
  • 在亚马逊云科技上利用Graviton4代芯片构建高性能Java应用(下篇)
  • 3.Kubernetes资源对象之pod
  • 828华为云征文|华为云Flexus X实例docker部署最新版禅道构建属于自己的项目管理平台
  • 文心智能体应用:美国旅游助手的诞生
  • 【进展报告】9.9-9.12
  • Cargo 入门
  • 远程控制软件有哪些?不多,给你奉上这6款神仙软件
  • nodeJS学习笔记——包npm(2)
  • vue3利用ref操作dom元素