<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>QEMU - 标签 - huxiang.bond</title><link>https://huxiang.bond/tags/qemu/</link><description>QEMU - 标签 - huxiang.bond</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>admin@huxiang.bond (huxiang)</managingEditor><webMaster>admin@huxiang.bond (huxiang)</webMaster><copyright>huxiang.bond</copyright><lastBuildDate>Fri, 30 Oct 2026 11:00:00 +0800</lastBuildDate><atom:link href="https://huxiang.bond/tags/qemu/" rel="self" type="application/rss+xml"/><item><title>openEuler RISC-V 零基础入门实操：从装 QEMU 到跑通第一个 RISC-V 程序</title><link>https://huxiang.bond/posts/openeuler-riscv-beginner/</link><pubDate>Fri, 30 Oct 2026 11:00:00 +0800</pubDate><author>admin@huxiang.bond (huxiang)</author><guid>https://huxiang.bond/posts/openeuler-riscv-beginner/</guid><description><![CDATA[<div class="featured-image">
                <img src="/welcome/card_futuristic.jpg" referrerpolicy="no-referrer">
            </div><blockquote>
<p>作者：一名在 x86 电脑上&quot;白嫖&quot;到一台 RISC-V 电脑的学习者</p>
<p>关键词：openEuler、RISC-V、QEMU、虚拟机、gcc、hello world</p>
</blockquote>
<h2 id="一写在前面为什么我非要折腾一台假的-risc-v-电脑">一、写在前面：为什么我非要折腾一台&quot;假&quot;的 RISC-V 电脑</h2>
<p>最近在跟着 openEuler RISC-V 相关的学习资料做入门实践，第一道坎就是：<strong>我手上没有 RISC-V 开发板，怎么办？</strong></p>
<p>答案就是 QEMU——一个开源模拟器，可以在我的 x86 电脑上&quot;假装&quot;出一台完整的 RISC-V 电脑（CPU、内存、硬盘、网卡全都有），然后在里面装一个真正的 openEuler RISC-V 操作系统。更妙的是，<strong>QEMU 用的是纯软件模拟（TCG 技术），不需要 CPU 支持硬件虚拟化</strong>，也不用去 BIOS 里开 VT-x，装完就能用。</p>
<p>这篇文章就是我的完整实操记录：从装 QEMU、下载镜像、启动虚拟机，到在 riscv64 系统里编译运行我写的第一个 C 程序。全程第一人称踩坑实录，零基础可跟。</p>
<p><strong>我的环境</strong>：Windows 11 + WSL2（Ubuntu 22.04），所有命令都在 WSL 终端里执行。如果你用 Windows 原生 PowerShell 或 macOS，命令大同小异，我在文末踩坑区会标注差异点。</p>
<h2 id="二环境准备装-qemu-并完成验证三连">二、环境准备：装 QEMU 并完成&quot;验证三连&quot;</h2>
<h3 id="21-安装-wslwindows-用户">2.1 安装 WSL（Windows 用户）</h3>
<p>管理员身份打开 PowerShell，执行：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-powershell">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">wsl</span> <span class="p">-</span><span class="n">-install</span></span></span></code></pre></div></div>
<p>重启后按提示设置 Ubuntu 的用户名和密码（<strong>记好这个密码，sudo 要用</strong>）。装好后打开&quot;开始菜单 → Ubuntu&quot;进入 Linux 终端。</p>
<h3 id="22-安装-qemu">2.2 安装 QEMU</h3>
<p>在 WSL 终端里依次执行：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update
</span></span><span class="line"><span class="cl">sudo apt install -y qemu-system-misc qemu-utils</span></span></code></pre></div></div>
<p><code>qemu-system-misc</code> 这个包里就包含了 riscv64 等&quot;杂项架构&quot;的全系统模拟器，<code>qemu-utils</code> 提供 <code>qemu-img</code> 工具。装完 <code>qemu-system-riscv64</code> 就在系统里了。</p>
<h3 id="23-验证三连装完必做">2.3 验证三连（装完必做）</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">qemu-system-riscv64 --version
</span></span><span class="line"><span class="cl">qemu-system-riscv64 -machine <span class="nb">help</span> <span class="p">|</span> grep virt
</span></span><span class="line"><span class="cl">qemu-img --version</span></span></code></pre></div></div>
<p>我的实际输出：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">QEMU emulator version 8.2.2 (Debian 1:8.2.2+dfsg-1~22.04.5)
</span></span><span class="line"><span class="cl">Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">virt              RISC-V VirtIO Board (default)</span></span></code></pre></div></div>
<p>三条全过 = QEMU 装好了。<strong>要求版本号 ≥ 7.0</strong>，因为 openEuler 24.03 LTS 的官方镜像和启动脚本是按新版 QEMU 写的；<code>-machine help</code> 里能看到 <code>virt</code> 行说明模拟器支持 openEuler 官方镜像默认的机器型号。</p>
<blockquote>
<p>💡 踩坑预警：如果你的 WSL 里 <code>apt update</code> 卡住不动，多半是 Ubuntu 官方源在大陆网络慢，把 <code>/etc/apt/sources.list</code> 里的 <code>archive.ubuntu.com</code> 换成清华或阿里镜像源再试。</p>
</blockquote>
<h2 id="三下载镜像三个文件一个都不能少">三、下载镜像：三个文件，一个都不能少</h2>
<p>打开 openEuler 官方下载页：<code>https://www.openeuler.org/zh/download/</code>，找到 <strong>24.03 LTS</strong> 版本 → <strong>RISC-V 架构</strong>分区 → 虚拟机镜像区，下载这四个文件到 <code>~/riscv-lab/</code> 目录：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">openEuler-24.03-LTS-SP3-riscv64.qcow2.xz   # 磁盘镜像压缩包，约 3-5GB，最大最慢
</span></span><span class="line"><span class="cl">RISCV_VIRT_CODE.fd                          # UEFI 固件-代码（几 MB）
</span></span><span class="line"><span class="cl">RISCV_VIRT_VARS.fd                          # UEFI 固件-变量（几 MB）
</span></span><span class="line"><span class="cl">start_vm.sh                                 # 官方启动脚本（几 KB）</span></span></code></pre></div></div>
<p>三个文件的角色：<code>.qcow2.xz</code> 是<strong>整块硬盘</strong>（装了 openEuler 系统，被 xz 压缩打包了）；两个 <code>.fd</code> 是<strong>UEFI 固件</strong>（电脑开机第一段代码，负责把系统从硬盘里叫醒）；<code>start_vm.sh</code> 是官方写好的启动说明书。</p>
<p>下载完做两件事：</p>
<ol>
<li><strong>看大小</strong>：qcow2.xz 应该有 3-5GB，如果只有几百 MB，多半是下载中断了，删掉重下。</li>
<li><strong>校验完整性</strong>：用 <code>sha256sum</code> 对比下载页给的校验值，整串一致才放心：</li>
</ol>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/riscv-lab
</span></span><span class="line"><span class="cl">sha256sum openEuler-24.03-LTS-SP3-riscv64.qcow2.xz</span></span></code></pre></div></div>
<blockquote>
<p>⏳ 踩坑预警：<strong>镜像下载慢</strong>是大陆网络的老大难。我的解法三件套：① 用支持断点续传的下载工具（IDM/迅雷），断了不用从头来；② 换清华镜像源 <code>https://mirrors.tuna.tsinghua.edu.cn/openeuler/</code>，路径结构和官方站一致；③ 实在不行就半夜下（说多了都是泪，但真的快）。</p>
</blockquote>
<h2 id="四解压--启动那条-200-字符的长命令逐参数看懂">四、解压 + 启动：那条 200 字符的长命令，逐参数看懂</h2>
<h3 id="41-解压镜像">4.1 解压镜像</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/riscv-lab
</span></span><span class="line"><span class="cl">xz -dk openEuler-24.03-LTS-SP3-riscv64.qcow2.xz</span></span></code></pre></div></div>
<p><code>-d</code> 是解压（decompress），<code>-k</code> 是保留原压缩包。解压要等 1-5 分钟，终端没输出是正常的。完成后 <code>ls -lh</code> 应该能看到不带 <code>.xz</code> 后缀的 qcow2 文件（解压后约 5-7GB）。</p>
<h3 id="42-启动命令逐参数拆解">4.2 启动命令逐参数拆解</h3>
<p>第一次启动，我建议直接用官方 <code>start_vm.sh</code>，但<strong>一定要看懂它在干什么</strong>。它的核心就是下面这条命令（我整理成了经典写法，每个参数独立一行，行尾 <code>\</code> 只是续行符）：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">qemu-system-riscv64 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -machine virt -m 4G -smp <span class="m">4</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -drive <span class="nv">file</span><span class="o">=</span>openEuler-24.03-LTS-SP3-riscv64.qcow2,format<span class="o">=</span>qcow2,id<span class="o">=</span>hd0 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -device virtio-blk-device,drive<span class="o">=</span>hd0 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -netdev user,id<span class="o">=</span>n0,hostfwd<span class="o">=</span>tcp::12055-:22 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -device virtio-net-device,netdev<span class="o">=</span>n0 <span class="se">\
</span></span></span><span class="line"><span class="cl">  -nographic</span></span></code></pre></div></div>
<p>用人话翻译：<strong>&ldquo;QEMU，请模拟一台 RISC-V 电脑（virt 型号），给它 4GB 内存、4 个 CPU 核心；把 qcow2 文件当作硬盘接上；给它一张能上网的虚拟网卡，并把宿主机的 12055 端口转发到虚拟机的 22 号端口；不开图形窗口，所有输出走终端。&rdquo;</strong></p>
<p>各参数逐个说：</p>
<table>
	<thead>
			<tr>
					<th>参数</th>
					<th>含义</th>
					<th>去掉会怎样</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>-machine virt</code></td>
					<td>机器型号，<code>virt</code> 是 RISC-V 世界最常用的虚拟主板</td>
					<td>报错 <code>No machine specified</code></td>
			</tr>
			<tr>
					<td><code>-m 4G</code></td>
					<td>内存 4GB（从宿主机&quot;借&quot;走的，别开太大）</td>
					<td>内存太小起不来</td>
			</tr>
			<tr>
					<td><code>-smp 4</code></td>
					<td>4 个 CPU 核心（纯软件模拟，核给多了宿主机反而卡）</td>
					<td>默认 1 核，慢但能跑</td>
			</tr>
			<tr>
					<td><code>-drive ...</code></td>
					<td>定义硬盘：<code>file=</code> 指定 qcow2 文件，<code>format=qcow2</code> 声明格式，<code>id=hd0</code> 起名</td>
					<td>系统无盘可用</td>
			</tr>
			<tr>
					<td><code>-device virtio-blk-device,drive=hd0</code></td>
					<td>把硬盘 <code>hd0</code> 通过 virtio 高速总线接上主板</td>
					<td>硬盘&quot;看不见&quot;，Kernel panic</td>
			</tr>
			<tr>
					<td><code>-netdev user,...hostfwd=tcp::12055-:22</code></td>
					<td>用户模式网卡 + <strong>端口转发</strong>：访问宿主机 12055 端口 = 访问 VM 的 22 端口（SSH）</td>
					<td>VM 无法上网、无法 SSH</td>
			</tr>
			<tr>
					<td><code>-device virtio-net-device,netdev=n0</code></td>
					<td>把网卡接上主板</td>
					<td>网卡&quot;看不见&quot;</td>
			</tr>
			<tr>
					<td><code>-nographic</code></td>
					<td>不开图形窗口，虚拟机的&quot;屏幕&quot;直接接到终端</td>
					<td>尝试开图形窗口，无图形环境会报错</td>
			</tr>
	</tbody>
</table>
<blockquote>
<p>📌 这里最重要、全书必考的是 <strong><code>hostfwd=tcp::12055-:22</code></strong>：它决定了你后面能不能 SSH 进虚拟机。22 是 SSH 默认端口，12055 是宿主机上的映射端口（高位端口，避免和宿主机自己的 22 冲突）。想换就换，但换了以后 SSH 命令的 <code>-p</code> 参数要跟着改。</p>
</blockquote>
<h3 id="43-启动你会看到四个阶段">4.3 启动！你会看到四个阶段</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./start_vm.sh</span></span></code></pre></div></div>
<blockquote>
<p>💡 踩坑预警：如果报 <code>Permission denied</code>，说明脚本没有执行权限，先 <code>chmod +x start_vm.sh</code> 再运行。如果报 <code>command not found</code>，检查 <code>pwd</code> 确认你在 <code>riscv-lab</code> 目录里。</p>
</blockquote>
<p>回车后耐心等待 1-3 分钟，启动日志按这个顺序刷屏：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">OpenSBI v1.4
</span></span><span class="line"><span class="cl">   ____                    _____ ____ _____
</span></span><span class="line"><span class="cl">  / __ \                  / ____|  _ \_   _|
</span></span><span class="line"><span class="cl">...（固件先醒来，确认自己在 QEMU 的 virt 机器上）
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[    0.000000] Linux version 6.6.0-76.0.0.76.oe2403.riscv64 (oe-build@localhost) ...
</span></span><span class="line"><span class="cl">[    0.000000] CPU: rv64imafdc_zicsr_zifencei_zba_zbb_zbc_zbs ...
</span></span><span class="line"><span class="cl">[    0.000000] 4 CPUs detected
</span></span><span class="line"><span class="cl">[    1.234567] virtio_blk virtio0: [vda] 62914560 512-byte logical blocks (32.2 GB)
</span></span><span class="line"><span class="cl">[    3.456789] systemd[1]: Running in virtual machine.
</span></span><span class="line"><span class="cl">[  OK  ] Started OpenSSH server daemon.
</span></span><span class="line"><span class="cl">[  OK  ] Reached target Multi-User System.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">openEuler Linux 24.03 (LTS)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Kernel 6.6.0-76.0.0.76.oe2403.riscv64 on an riscv64
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">localhost login:</span></span></code></pre></div></div>
<p>看到 <code>login:</code> 提示符，<strong>你的第一台 RISC-V 虚拟机就启动成功了！</strong> 重点看三处：<code>Linux version ...riscv64</code>（RISC-V 世界的内核）、<code>virtio_blk ... [vda]</code>（你的 qcow2 硬盘被识别了）、<code>on an riscv64</code>（架构实锤）。</p>
<h3 id="44-登录--立刻改密码">4.4 登录 + 立刻改密码</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">localhost login: root
</span></span><span class="line"><span class="cl">Password: openEuler12#$</span></span></code></pre></div></div>
<p><strong>openEuler RISC-V 官方镜像默认密码是 <code>openEuler12#$</code></strong>（<code>#$</code> 是密码的一部分，一共 13 个字符，别把 <code>#</code> 打成中文的）。输密码时屏幕什么都不显示——这是 Linux 的安全设计，不是键盘坏了，盲打回车即可。</p>
<p>登录成功提示符会变成 <code>[root@localhost ~]#</code>（<code>#</code> 是 root 用户的标志）。第一件事改密码：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">passwd</span></span></code></pre></div></div>
<blockquote>
<p>⚠️ 默认密码全世界都知道，<strong>登录后必须立刻改</strong>。密码至少 8 位，建议字母+数字+符号混合。忘了密码很麻烦（要进单用户模式重置），一定记牢。</p>
</blockquote>
<h2 id="五换个姿势进门ssh-远程登录">五、换个姿势进门：SSH 远程登录</h2>
<p>在 QEMU 黑窗口里操作只是第一步，真实服务器工作流全靠 SSH。回到<strong>宿主机</strong>终端：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ssh root@127.0.0.1 -p <span class="m">12055</span></span></span></code></pre></div></div>
<p>第一次连接会弹&quot;主机指纹确认&quot;提示（这是 SSH 的防伪机制，防止有人冒充你的 VM），输入完整的 <code>yes</code> 回车，然后输 VM 的 root 密码。登录后验证一下：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">uname -m</span></span></code></pre></div></div>
<p>输出 <code>riscv64</code>——<strong>你在 x86 宿主机上，手却伸进了 riscv64 的虚拟机</strong>，这就是 12055 端口转发的功劳。</p>
<blockquote>
<p>💡 进阶一步：<code>ssh-keygen -t ed25519</code> 生成密钥对，再 <code>ssh-copy-id root@127.0.0.1 -p 12055</code> 把公钥登记进 VM，以后 <code>ssh root@127.0.0.1 -p 12055</code> 免密直进，传文件用 <code>scp -P 12055 文件 root@127.0.0.1:/root/</code>（注意 <strong>scp 是大写 <code>-P</code>，ssh 是小写 <code>-p</code></strong>，这个坑坑过无数人）。</p>
</blockquote>
<h2 id="六第一个-risc-v-程序从装-gcc-到跑通-hello">六、第一个 RISC-V 程序：从装 gcc 到跑通 hello</h2>
<h3 id="61-装编译器">6.1 装编译器</h3>
<p>在 VM 里执行（注意提示符是 <code>[root@localhost ~]#</code>，别在宿主机敲）：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dnf install -y gcc</span></span></code></pre></div></div>
<p>注意输出里这行：<code>gcc riscv64 12.3.1-2.oe2403</code>——你装的是 <strong>riscv64 版的 gcc</strong>，它编译出来的机器码就是 RISC-V 方言，这就是&quot;原生编译&quot;。验证：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gcc --version</span></span></code></pre></div></div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">gcc (GCC) 12.3.1 20230508 (openEuler 12.3.1-2.oe2403)</span></span></code></pre></div></div>
<h3 id="62-写-helloc">6.2 写 hello.c</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nano hello.c</span></span></code></pre></div></div>
<p>输入（强烈建议手敲一遍，别复制）：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-c">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Hello from RISC-V!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p><code>Ctrl+O</code> 保存，<code>Ctrl+X</code> 退出。逐行含义一句话版：<code>#include &lt;stdio.h&gt;</code> 是引入标准输入输出库的&quot;说明书&quot;；<code>int main(void)</code> 是程序唯一的大门，CPU 从这里开始执行；<code>printf</code> 把文字打到屏幕，<code>\n</code> 是换行，行尾分号 <code>;</code> 是 C 语言的&quot;句号&quot;（漏掉它是新手第一大报错来源）；<code>return 0</code> 表示程序正常结束。</p>
<h3 id="63-编译--运行--验证架构三连">6.3 编译 → 运行 → 验证架构（三连）</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gcc hello.c -o hello
</span></span><span class="line"><span class="cl">./hello
</span></span><span class="line"><span class="cl">file hello</span></span></code></pre></div></div>
<p>我的实际输出：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Hello from RISC-V!
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">hello: ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1, for GNU/Linux 4.15.0, not stripped</span></span></code></pre></div></div>
<p>三个要点：</p>
<ol>
<li><strong><code>gcc hello.c -o hello</code> 编译成功是&quot;沉默&quot;的</strong>——没有任何输出就是最好的输出（注意 <code>-o</code> 是小写字母 o，不是数字 0）。</li>
<li><strong>运行必须写 <code>./hello</code></strong>——Linux 默认不在当前目录找命令，直接敲 <code>hello</code> 会报 <code>command not found</code>。</li>
<li><strong><code>file hello</code> 是本章最有成就感的时刻</strong>：输出里 <code>UCB RISC-V</code> 就是架构实锤（UCB = 加州大学伯克利分校，RISC-V 的诞生地，名字留在了 ELF 格式里）；<code>RVC</code> 表示用了压缩指令扩展；<code>/lib/ld-linux-riscv64-lp64d.so.1</code> 是 riscv64 的程序加载器。</li>
</ol>
<p><strong>强烈建议做个对照实验</strong>：把 hello.c 在 x86 宿主机上也编译一次，<code>file</code> 输出会变成 <code>ELF 64-bit ... x86-64 ...</code>——同一个源码，不同架构的编译器，产出不同&quot;方言&quot;的机器码。把 VM 里编的 <code>hello</code> 拷到宿主机运行，会报 <code>Exec format error</code>（架构不对，不是文件坏了）。<strong>架构的壁垒，这一刻你亲手摸到了。</strong></p>
<h2 id="七踩坑合集我替你踩过的坑">七、踩坑合集：我替你踩过的坑</h2>
<table>
	<thead>
			<tr>
					<th>现象</th>
					<th>原因</th>
					<th>解法</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>执行脚本报 <code>Permission denied</code></td>
					<td>脚本没有执行权限</td>
					<td><code>chmod +x start_oe.sh</code>，或改用 <code>bash start_oe.sh</code></td>
			</tr>
			<tr>
					<td>启动报 <code>Failed to bind socket: Address already in use</code></td>
					<td>12055 端口被占（上次 VM 没关干净 / 别的程序占用）</td>
					<td>换端口（改脚本里的 hostfwd 和 SSH 的 <code>-p</code>）；查占用：Windows <code>netstat -ano | findstr 12055</code>，Linux <code>ss -ltnp | grep 12055</code></td>
			</tr>
			<tr>
					<td>镜像下载慢 / 中断</td>
					<td>官方站在大陆网络慢</td>
					<td>清华镜像源 <code>mirrors.tuna.tsinghua.edu.cn/openeuler/</code>；IDM/迅雷断点续传；<code>sha256sum</code> 校验完整性</td>
			</tr>
			<tr>
					<td><code>ssh: connect to host 127.0.0.1 port 22: Connection refused</code></td>
					<td><strong>忘了写 <code>-p 12055</code></strong>，ssh 默认去敲 22 端口</td>
					<td>命令补上 <code>-p 12055</code></td>
			</tr>
			<tr>
					<td>SSH 报 <code>Connection refused</code>（端口写对了）</td>
					<td>VM 没启动 / 防火墙拦截 / VM 里 sshd 没运行</td>
					<td>确认 QEMU 窗口还开着；Windows 防火墙放行 qemu；VM 里 <code>systemctl start sshd</code></td>
			</tr>
			<tr>
					<td>输密码没反应</td>
					<td><strong>正常现象</strong>，终端故意不回显密码</td>
					<td>盲打回车即可</td>
			</tr>
			<tr>
					<td><code>bash: hello: command not found</code></td>
					<td>运行少了 <code>./</code> 前缀</td>
					<td>写 <code>./hello</code></td>
			</tr>
			<tr>
					<td><code>bash: ./hello: cannot execute binary file: Exec format error</code></td>
					<td>把 x86 编译的程序拷进 riscv64 VM 跑（反过来也一样）</td>
					<td>在目标机器上重新编译，或学交叉编译</td>
			</tr>
			<tr>
					<td>编译报 <code>stray '\...' in program</code></td>
					<td>代码里混入全角字符（中文引号/分号，输入法没切回）</td>
					<td>按 <code>文件名:行号:列号</code> 定位，改成英文半角</td>
			</tr>
			<tr>
					<td>杀毒软件把 QEMU 当病毒</td>
					<td>误报（模拟器常被误判为&quot;黑客工具&quot;）</td>
					<td>从官网 qemu.org 下载，加白名单（安装目录 + 工作目录）</td>
			</tr>
	</tbody>
</table>
<h2 id="八总结我这一路学到了什么">八、总结：我这一路学到了什么</h2>
<p>从零到跑通第一个 RISC-V 程序，我完成了三件有里程碑意义的事：</p>
<ol>
<li><strong>装好了 QEMU</strong>，用纯软件模拟在 x86 电脑上&quot;无中生有&quot;了一台 RISC-V 电脑——不需要真机，不需要硬件虚拟化。</li>
<li><strong>看懂了一条 200 字符的 QEMU 启动命令</strong>：<code>-machine</code> 选机型、<code>-m</code> 给内存、<code>-smp</code> 给核数、<code>-drive</code> 挂硬盘、<code>-netdev hostfwd</code> 做端口转发、<code>-nographic</code> 走终端。从此虚拟机在我眼里不再是&quot;黑魔法&quot;，而是一台参数明确的电脑。</li>
<li><strong>在 riscv64 上原生编译并运行了自己的程序</strong>，并且用 <code>file hello</code> 亲眼看到了 <code>UCB RISC-V</code> 的字样——那一刻我才真正理解了什么是&quot;架构&quot;：同一个 <code>printf</code>，x86 和 RISC-V 会翻译成完全不同的机器码，程序必须在目标架构上编译才能运行。</li>
</ol>
<p>下一步我准备挑战<strong>交叉编译</strong>：在 x86 宿主机上用 <code>riscv64-linux-gnu-gcc</code> 编出 riscv64 的程序，再用 <code>qemu-riscv64</code>（用户态模拟）直接验证——&ldquo;编译放宿主机、运行验证靠模拟器&rdquo;，这是 RISC-V 软件生态里最常用的生产工作流，也是我实习测评工作的标准姿势。等我把 RVV 向量扩展也玩明白了，再来分享第二篇。</p>
<p>如果这篇文章帮到了你，或者你在实操中遇到了其他坑，欢迎评论区交流。<strong>RISC-V 的世界，入门真的没有想象中那么难。</strong></p>
]]></description></item></channel></rss>