RVOS-1.环境搭建与系统引导
0.环境搭建
riscv-operating-system-mooc: 开放课程《循序渐进,学习开发一个 RISC-V 上的操作系统》配套教材代码仓库。 mirror to https://github.com/plctlab/riscv-operating-system-mooc
在 Ubuntu 20.04 以上环境下我们可以直接使用官方提供的 GNU工具链和 QEMU 模拟器,执行如下命令在线安装即可开始试验:
$ sudo apt update
$ sudo apt install build-essential gcc make perl dkms git gcc-riscv64-unknown-elf gdb-multiarch qemu-system-misc
构建和使用说明:
- `make`:编译构建
- `make run`:启动 `qemu` 并运行
- `make debug`:启动调试
- `make code`:反汇编查看二进制代码
- `make clean`:清理
1. 系统引导
1.1 引导程序入口
硬件地址映射:
系统引导过程:
内核被加载到DRAM的地址 0x8000-0000
,引导加载程序被加载到ROM的地址 0x0000-F000
到 0x0000-0000
。
正常是固化在ROM的程序来引导,找到bootloader程序(BL0阶段)。但这里我们使用模拟器QEMU,在makefile里面指定了内核程序入口:在启动过程中,内核的入口点通常是位于ELF文件中的一个特定位置,这个位置由链接器脚本或者链接选项指定。在Makefile中,链接选项 -Ttext=0x80000000
指定了内核的文本段(代码段)应该被加载到内存地址 0x80000000
处。这意味着当QEMU启动时,它会将内核的代码和数据加载到这个地址,并且从这个地址开始执行。
总而言之:
run
目标使用QEMU模拟器运行内核,运行的确实是内核os.elf,并且在ELF文件里面的0x80000000地方开始运行。
但是我们还是分析一下这段汇编
auipc t0, 0x0 addi a2, t0, 40 #可能是栈 csrr a0, mhartid #将硬件线程ID写入寄存器 a0。 lw a1, 32(t0) #参数 lw t0, 24(t0) #内核的入口地址存放处 jr t0 #jr t0:跳转到寄存器 t0 指向的地址,即内核的入口地址。 start: .word
没看明白,求大佬指点!
1.2 引导程序
这里类似于bootloader的 BL1阶段:
BL1阶段通常负责:
- 初始化CPU和基本的硬件设备。
- 设置栈指针。
- 跳转到下一个阶段的bootloader(如BL2)或直接跳转到操作系统。
start.S
:
#include "platform.h"# size of each hart's stack is 1024 bytes# 用于分配一段内存空间 “External Public Uninitialized Block".equ STACK_SIZE, 1024.global _start.text
_start:# park harts with id != 0让除了0号核的其他核都进入park状态csrr t0, mhartid # read current hart idmv tp,t0 # save current hart id to tpbnez t0,park # if hart id != 0, park# Setup stacks, the stack grows from bottom to top, so we put the# stack pointer to the very end of the stack range.slli t0, t0, 10 # shift left the hart id by 1024-->(for multiple harts)la sp, stacks + STACK_SIZE # set the initial stack pointer# to the end of the first stack spaceadd sp, sp, t0 # move the current hart stack pointer# to its place in the stack spacej start_kernel # hart 0 jump to cpark:wfij park# In the standard RISC-V calling convention, the stack pointer sp# is always 16-byte aligned.
.balign 16
stacks:.skip STACK_SIZE * MAXNUM_CPU # allocate space for all the harts stacks.end # End of file
kernel.c
void start_kernel(void)
{while (1) {}; // stop here!
}
platform.h
#ifndef __PLATFORM_H
#define __PLATFORM_H#define MAXNUM_CPU 8#endif // __PLATFORM_H
运行结果:成功进入void start_kernel(void);
疑问:这些文件怎么组织在一起的?
文件之间的联系是通过链接器来建立的。链接器(Linker)是编译过程中的一个工具,它将编译后的目标文件(Object Files,通常是
.o
文件)和库文件链接在一起,生成一个可执行文件(Executable File)或库文件(Library File)
。在此项目中,链接过程是通过 Makefile 控制的。Makefile 中定义了如何编译和链接项目:
OBJS_ASM 和 OBJS_C:这些变量定义了汇编和 C 语言的目标文件(Object Files)。
ELF 和 BIN:
ELF
是链接后的可执行文件,BIN
是可执行文件的二进制格式。LDFLAGS:链接器标志,用于指定链接器的行为。在您的 Makefile 中,
LDFLAGS
可以是-T ${OUTPUT_PATH}/os.ld.generated
(使用链接脚本)或-Ttext=0x80000000
(指定文本段的起始地址)。链接命令:
${ELF}: ${OBJS}ifeq (${USE_LINKER_SCRIPT}, true)${CC} -E -P -x c ${DEFS} ${CFLAGS} os.ld > ${OUTPUT_PATH}/os.ld.generatedendif${CC} ${CFLAGS} ${LDFLAGS} -o ${ELF} $^${OBJCOPY} -O binary ${ELF} ${BIN}
这段代码首先检查是否使用链接脚本,如果是,则生成链接脚本文件。然后使用
CC
(交叉编译器)和LDFLAGS
链接目标文件,生成 ELF 文件。最后,使用OBJCOPY
将 ELF 文件转换为二进制格式。默认目标:
.DEFAULT_GOAL := all all: ${OUTPUT_PATH} ${ELF}
默认目标是
all
,它依赖于OUTPUT_PATH
和ELF
文件。通过这些步骤,Makefile 确保了所有源文件被正确编译和链接,生成最终的可执行文件。链接器根据链接脚本(如果使用)或链接器标志来确定如何将各个目标文件和库文件组合在一起。
参考—汪老师讲的太好了!!!!:
1.3 RISC-V寄存器_RISC-V体系结构编程与实践(第2版)
【[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春】 https://www.bilibili.com/video/BV1Q5411w7z5/?p=19&share_source=copy_web&vd_source=d63943fdb26087d14a536adf35c52d6b
相关文章:
RVOS-1.环境搭建与系统引导
0.环境搭建 riscv-operating-system-mooc: 开放课程《循序渐进,学习开发一个 RISC-V 上的操作系统》配套教材代码仓库。 mirror to https://github.com/plctlab/riscv-operating-system-mooc 在 Ubuntu 20.04 以上环境下我们可以直接使用官方提供的 GNU工具链和 QEM…...
Java List<JSONObject> 转换为 List<实体类>
可以使用 Fastjson 的 toJavaObject 方法直接转换,无需中间序列化步骤。以下是具体实现和注意事项: import com.alibaba.fastjson.JSONObject; import java.util.List; import java.util.stream.Collectors;public class Converter {public static List…...
CesiumEarth v1.12 更新,支持安卓平板离线浏览3DTiles格式的三维倾斜模型
CesiumEarth v1.12 更新 2025年4月8日 阅读需 1 分钟 发布时间:2025年04月08日 新增用户登录: 从1.12版本开始需要通过登录方可使用CesiumEarth 账号可以通过邮箱免费注册 后续将陆续发布云服务相关的功能 发布Desktop版本: Deskt…...
OpenEuler运维实战-系统资源监控与性能优化-CPU·内存·IO
CPU 基本概念定界定位思路常用CPU性能分析工具 基本概念 中央处理器(Central Processing Unit,简称CPU)是计算机的主要设备之一,其功能是解释计算机指令以及处理计算机软件中的数据。 物理核:可以真实看到的CPU核&…...
react实现SVG地图区域中心点呈现圆柱体,不同区域数据不同,圆柱体高度不同
效果图: 代码: import React, { useState, useEffect } from react;const InnerMongoliaMap () > {// 每个区域的数据(名称、中心坐标、圆柱体高度值)const [regionData, setRegionData] useState([{ id: "呼和浩特市…...
Qwen - 14B 怎么实现本地部署,权重参数大小:21GB
Qwen - 14B 权重参数大小:21GB 参数量与模型占用存储空间(GB)是不同概念。Qwen - 14B参数量约140亿 。其模型大小在不同精度下占用存储空间不同,如在一些资料中提到,Qwen - 14B在特定情况下占用空间约21GB 。实际存储…...
线程实现参考资料
参考 并发编程系列 - Java线程池监控及CompletableFuture详解_taskexecutor.execute没有执行如何监控到-CSDN博客 JAVA异步实现的四种方式_java异步编程的四种方法-CSDN博客 Java线程池深度解析与自定义实战-CSDN博客 Java8 CompletableFuture 异步多线程的实现_java_脚本之…...
python-63-前后端分离之图书管理系统的Flask后端
文章目录 1 flask后端1.1 数据库实例extension.py1.2 数据模型models.py1.3 .flaskenv1.4 app.py1.5 运行1.6 测试链接2 关键函数和文件2.1 请求视图类MethodView2.2 .flaskenv文件3 参考附录基于flask形成了图书管理系统的后端,同时对其中使用到的关键文件.flaskenv和函数类M…...
Qt网络编程之服务端
Qt网络编程之服务端 TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。它特别适合连续的数据传输。 1. 主要类和函数 1.1 QTcpServer 监听函数: bool QTcpServer::listen(const QHostAddress &address QHostAddress::…...
案例-流量统计
1.建一个data目录,在data下建log.txt文件 输入手机号码 上行流量 下行流量 2.在com.example.flow下建四个Java类3.flowBean flowMapper flowReducer flowDriver...
开源身份和访问管理方案之keycloak(二)管理员引导和恢复
文章目录 开源身份和访问管理方案之keycloak(二)管理员引导和恢复管理员引导和恢复在 Keycloak 启动时引导临时管理员帐户对于恢复丢失的管理员访问权限使用专用命令引导管理员用户或服务帐户创建一个管理员用户创建一个服务账号重新获得对具有更高安全性…...
TCP,UDP协议和域名地址
1.TCP(传输控制协议)是面向连接,UDP(用户数据报协议)是无连接的 2.应用层:FTP,HTTP,SMTP,TELNET,DNS,TFTP 传输层;TCP,UDP 网际层:IP,ICMP,ARP,RARP 3.TCP21:20端口数据传输;21端…...
算法进阶指南 分形
问题描述 分形,具有以非整数维形式充填空间的形态特征。通常被定义为: “一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。 现…...
2025年 npm淘宝镜像最新地址
查看当前镜像 npm config get registry 切换陶宝镜像源 npm config set registry https://registry.npmmirror.com/ 验证npm镜像源是否切换成功 npm config get registry 如果返回的地址是https://registry.npmmirror.com/,那么说明你已经成功切换到淘宝的npm…...
0基础 | 硬件 | LM386芯片
LM386芯片:音频功率放大器芯片 内部集成三极管功能将微弱信号放大20-200倍,并且驱动内阻为8Ω的扬声器注意CD系列芯片,内部集成MOS管 LM386特性 LM386主要由以下三个部分组成 内部电路 差分输入 差分输入 多个三极管左右对称,形…...
Spring Boot集成APK Parser库实现APK文件解析
目录 1. 添加依赖 2. 创建APK解析服务 3. 创建控制器 4. 测试 注意事项 在Spring Boot项目中集成APK Parser库并解析APK文件,可以按照以下步骤进行操作: 1. 添加依赖 在项目的pom.xml文件中添加apk-parser库的依赖: <dependency&…...
java基础 迭代Iterable接口以及迭代器Iterator
Itera迭代 Iterable < T>迭代接口(1) Iterator iterator()(2) forEach(Consumer<? super T> action)forEach结合Consumer常见场景forEach使用注意细节 (3)Spliterator spliterator() Iterator< T>迭代器接口如何“接收” Iterator<T>核心方法迭代器的…...
Linux: network: tcpdump: packets dropped by kernel
文章目录 最近遇到一个问题原因libpcap/tcpdump 接口linux/libpcap 接口内核的处理原因可能有以下几种:解决方法:man pcap_stats最近遇到一个问题 tcpdump命令显示有dropped的包,而且是被内核drop的。 [root@-one-01 ~]# tcpdump -i any udp and port 8080 -v -w /root/udp…...
TCP三次握手和TCP四次挥手
一 TCP三次握手 TCP建立连接的过程叫做握手,握手需要客户端和服务器之间交换三个TCP报文段。如图所示,假设主机A为TCP客户端,主机B为TCP服务端。在最初时间,两端的TCP进程都是处于CLOSED状态 (1)主机A主动…...
博途 TIA Portal之1200做主站与调试助手的TCP通讯
博途支持的通讯非常多,常见的有S7、TCP/IP,UDP等等,本文将演示TCP的通讯,通讯的双方是1200PLC和调试助手之间,编程采用ST语言。 1、硬件准备 1200PLC一台,带调试助手的PC机一台,调试助手是我经…...
第十天 - socket编程基础 - TCP/UDP服务开发 - 练习:简易端口扫描器
Python网络编程入门:从Socket到端口扫描器实战 一、前言:为什么要学网络编程? 在这个万物互联的时代,掌握网络编程技术就像拥有了一把打开互联网世界的钥匙。无论是开发聊天软件、网络游戏,还是构建分布式系统&#…...
欧税通香港分公司办公室正式乔迁至海港城!
3月20日,欧税通香港分公司办公室正式乔迁至香港油尖旺区的核心商业区海港城!左手挽着内地市场,右手牵起国际航道——这波乔迁选址操作堪称“地理课代表”! 乔迁仪式秒变行业大联欢!感谢亚马逊合规团队、亚马逊云、阿里国际站、Wayfair、coupang、美客多…...
Maven的安装配置-项目管理工具
各位看官,大家早安午安晚安呀~~~ 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连,小编尽全力做到更好 欢迎您分享给更多人哦 今天我们来学习:Maven的安装配置-项目管理工具 目录 1.什么是Maven?Maven用来干什么的?…...
【Linux篇】缓冲区的工作原理:如何影响你程序的输入输出速度
从内存到磁盘:缓冲区如何提升文件I/O效率 一. 缓冲区1.1 什么是缓冲区1.2 为什么要引入缓冲区1.3 缓冲区类型1.4 FILE1.4.1 基本概念1.4.2 FILE 结构体的作用1.4.3 FILE 的工作机制 二. 最后 在程序开发中,缓冲区是一个经常被提及却不容易深入理解的概念…...
编写junit测试类 import org.junit.Test;
1. 添加依赖 <!-- Spring Boot Starter Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 2. …...
初识数据结构——深入理解LinkedList与链表:吃透LinkedList与链表的终极指南
📌 深入理解LinkedList与链表:从原理到实战应用 🌟 引言 在Java集合框架中,LinkedList和ArrayList是最常用的两种列表结构。它们各有优劣,适用于不同的场景。本文将带你深入探索LinkedList的底层实现——链表&#x…...
C++版Qt之登录界面设计
在C开发中,使用Qt框架可以快速构建美观且功能强大的GUI应用程序。本文将介绍如何设计一个漂亮的登录界面,包括账号和密码输入框,并确保只有验证成功后才能进入主窗口。 项目结构 文件列表 LoginDialog.h:登录对话框的头文件Logi…...
Java logback框架日志输出中文乱码的解决方案(windows)
在Java开发中,日志记录是一个重要的部分,它可以帮我们定位问题、运行时监控、错误排查与故障恢复。但是,在有些情况下,使用Logback记录的中文日志会出现乱码,这会影响日志的可读性,给维护带来麻烦。本文将探…...
【c++】c/c++内存管理
小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 c系列专栏<—请点击 倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己! 目录 前言一、c语言内存管理二、一图搞懂c/c中的程序内存区域划分三、c内存管理1. new和d…...
【C++】Stack Queue 仿函数
📝前言: 这篇文章我们来讲讲STL中的stack和queue。因为前面我们已经有了string、vector和list的学习基础,所以这篇文章主要关注一些stack和queue的细节问题,以及了解一下deque(缝合怪)和priority_queue &am…...
Python:基于Flask框架的数据可视化系统
以下是一个基于Flask框架的数据可视化系统代码示例,包含核心功能实现: python 复制 # app.py 后端核心代码 from flask import Flask, render_template, jsonify import sqlite3 from collections import defaultdict import jieba import reapp Fla…...
JVM即时编译(JIT)
JVM基础回顾 Java 作为一门高级程序语言,由于它自身的语言特性,它并非直接在硬件上运行,而是通过编译器(前端编译器)将 Java 程序转换成该虚拟机所能识别的指令序列,也就是字节码,然后运行在虚拟机之上的;…...
JVM高阶架构:并发模型×黑科技×未来趋势解析
🚀前言 “你是否还在为synchronized锁竞争头疼?是否好奇ZGC如何实现亚毫秒停顿?Java的未来将走向何方? 本文将带你深入JVM最硬核的三大领域: 并发模型:揭秘happens-before如何保证多线程安全(…...
Java的JDK、JRE、JVM关系与作用
Java的JDK、JRE、JVM关系与作用 java中的JDK、JRE和JVM是三个核心组件,各自承担不同角色,且存在层级依赖关系 1. JVM(Java Virtual Machine,Java虚拟机) 是什么: JVM是虚拟的计算机,能够执行…...
XMLHttpRequest vs Fetch API:一场跨越时代的“浏览器宫斗剧“
## 序幕:两个API的"身世之谜" 在Web开发的江湖里,XMLHttpRequest(简称XHR)就像一位身经百战的老将,而Fetch API则是手持光剑的绝地武士。让我们先来段"DNA检测": - **XHR(…...
Windows Anaconda使用Sentence-BERT获取句子向量
1、安装Anaconda: Anaconda是一个流行的Python数据科学平台,它包含了许多科学计算和数据分析的库,包括transformers和sentence_transformers。虽然不是必需的,但使用Anaconda可以简化环境管理和依赖安装的过程。 可以从Anaconda官…...
【Java设计模式】第5章 工厂方法模式讲解
5. 工厂方法模式 5.1 工厂方法讲解 定义:定义一个创建对象的接口,由子类决定实例化的类,将对象创建延迟到子类。适用场景: 创建对象需要大量重复代码。客户端不依赖具体产品的创建细节。优点: 符合开闭原则,新增产品只需扩展子类。客户端仅依赖抽象接口,不依赖具体实现…...
结合 Less + CSS 变量实现切换主题
一开始的思路是通过 Less 变量作用范围 来切换 light 和 dark 主题,但 Less 本身不会动态监听类名变化,所以直接这样写是 不可行的,因为 Less 是 预处理语言,它在编译阶段就确定了 color 的值,而不是在运行时动态切换。…...
数据分析之python处理常用复杂转置数据
前段时间根据需求配合ai写了个转置excel代码,挺好用的,而且可以选择excel,不局限于excel存在哪个地方,都可以转置,但是转置后的excel记得要先创建放在转置文件的目录下。 原本的数据长这样 转置后则可以变为这样&…...
未来杭州:科技与诗意的时空交响曲
故事背景 故事发生在中国浙江杭州的未来科技时代,通过六个充满未来感的场景展现传统文明与尖端科技的完美融合。全篇无人物角色,专注于构建兼具东方美学与赛博朋克风格的沉浸式景观。 故事内容 从晨雾中浮现全息诗句的西湖,到吞吐智能包裹的运…...
彩虹表是什么
彩虹表是一种用于破解加密散列函数的预计算表,主要用于破解密码的哈希值。以下是关于加密文件与彩虹表的相关信息: 彩虹表的原理 • 时空折中:彩虹表基于时空折中理论,通过预先计算并存储大量可能的密码及其哈希值,减少…...
[BreachCTF 2025]
周末的这个居然一个密码都不会,作了4个pwn,给原码看着真方便 FSWn3d #define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <unistd.h>char buffer[152…...
行业案例 | 印度航空借助 Azure AI,提升智能航空体验
自2022年塔塔集团(Tata Group)接管以来,印度航空启动了全面现代化升级,不仅豪掷470架新飞机订单以重塑“以人为本”的品牌形象,更将数字化作为核心战略——将所有工作负载(包括全新官网)从本地数…...
【Java设计模式】第7章 建造者模式讲解
7-1 建造者模式讲解 1. 定义与类型 定义: 将复杂对象的构建与表示分离,使相同构建过程可创建不同表示。类型: 创建型模式。通俗解释: 分步构建含多组件的对象,流程固定但顺序灵活(如做菜时放盐顺序可变)。2. 适用场景 对象内部结构复杂(多属性或多步骤)。需将对象创建与…...
鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)
还在为组件状态混乱、页面跳转丢参数而头疼? 这篇博客将揭秘如何用鸿蒙ArkTS打造一个漂亮美观的智能计算器: ✅ 输入完整表达式,秒出结果——字符串切割简单计算 ✅ 状态管理黑科技——Provide/Consume 实现跨组件实时响应 ✅ 路由传参实战—…...
虚拟机上安装openEuler和openGauss数据库
1.虚拟机版本选择VM 16 PRO 2.openEuler版本选择openEuler-22.03-LTS-SP4-x86_64 下载地址:https://mirrors.aliyun.com/openeuler/openEuler-22.03-LTS-SP4/ISO/x86_64/openEuler-22.03-LTS-SP4-x86_64-dvd.iso 3.虚拟机安装openEuler过程: 4.安装ope…...
深入解析 Jenkins Agent 的 .jnlp 启动文件
🧩 深入解析 Jenkins Agent 的 .jnlp 启动文件 在 Jenkins 中,通过 JNLP(Java Network Launch Protocol)方式连接 Agent 是一种常见且灵活的方式。你可能曾见过类似这样的命令: java -jar agent.jar -jnlpUrl file:/…...
在 macOS 上连接 PostgreSQL 数据库(pgAdmin、DBeaver)
在 macOS 上连接 PostgreSQL 数据库 pgAdmin 官方提供的图形化管理工具,支持 macOS。 下载地址:https://www.pgadmin.org/ pgAdmin 4 是对 pgAdmin 的完全重写,使用 Python、ReactJs 和 Javascript 构建。一个用 Electron 编写的桌面运行时…...
HarmonyOS Next~鸿蒙系统原生流畅性创新解析:预加载技术与全栈优化的革命性突破
鸿蒙系统原生流畅性创新解析:预加载技术与全栈优化的革命性突破 一级类目:鸿蒙创新特性 | 二级类目:原生流畅 鸿蒙系统(HarmonyOS)自诞生以来,始终以“天生流畅”为核心目标,其原生流畅性不仅…...
【图像处理】:opencv实现模糊图像处理和对比度增强
opencv实现模糊图像处理和对比度增强 模糊图像处理**方法 1:Wiener 反卷积(已知模糊核)****方法 2:非锐化掩码(Unsharp Masking)****方法 3:拉普拉斯锐化(Laplacian Sharpening&…...