WSL2通过主机转发流量,实现与开发板互相ping通

wsl 的网络模式

WSL(尤其是 WSL2)和主机不在同一网段却能双向通信,

核心原因是WSL2 的 NAT 网络架构并非普通的局域网模式,

而是通过 Windows 内核内置的专属虚拟网络栈+系统级地址转换 / 端口转发实现的主机内部虚拟通信,这种通信不走物理局域网,因此无需 "同一网段",

这也是 NAT 模式下 WSL 能 ping 通主机、却不能直接访问开发板的关键区别。

WSL2 启动时,Windows 会自动充当这个虚拟网络的NAT 网关,WSL 的所有网络请求都会先转发到 Windows 内核的网络层,再由主机的物理网卡(WiFi / 有线)对外发送。

主机是 WSL 的 "网络出口",出口和内部节点的通信,自然不用同一网段。

Windows 会自动维护一张WSL 地址映射表,即使 WSL 是 172 段,主机也能:

直接识别 WSL 的虚拟 IP(如 172.28.223.228),并建立双向通信;

同时支持localhost端口转发(WSL 的端口会自动映射到主机的localhost,比如 WSL 的 8080 端口,主机用localhost:8080就能访问)。

通过 windos实现端口转发

管理员权限打开 Windows 终端(PowerShell),执行以下命令(一键配置转发规则):

bash 复制代码
# 1. 添加端口转发:主机2222端口 → 开发板192.168.1.134的22端口
netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=22 connectaddress=192.168.1.134

# 2. 验证转发规则是否生效(能看到2222→192.168.1.134:22的规则即成功)
netsh interface portproxy show all

后续若想删除该规则,

bash 复制代码
netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=0.0.0.0

Windows 终端执行,找到主机 WiFi 的 IP(192.168.1.x 网段):

bash 复制代码
ipconfig | findstr "无线局域网适配器 WLAN" -A 5

记下来IPv4 地址,

telnet测试转发是否成功

这就是连接成功了,
退出按 ctrl+]

之所以用 telnet测试,不用 ping,是因为 ping不能带端口号。

其实也可以直接 ssh测试,账号密码用开发板的,地址填 windos的就行。

尝试文件拷贝

WSL 中拷贝开发板 sysroot(核心)

bash 复制代码
# 1. 进入你的项目目录,创建sysroot文件夹
cd ~/project/InfraredThermometer && mkdir -p lubancat_sysroot

# 2. rsync拷贝(关键:端口2222,目标是主机IP,不是开发板IP)
sudo rsync -avz --delete -e "ssh -p 2222" \
  --exclude=/proc \
  --exclude=/sys \
  --exclude=/dev \
  --exclude=/tmp \
  --exclude=/run \
  --exclude=/mnt \
  --exclude=/media \
  cat@192.168.1.253:/ \
  ~/project/InfraredThermometer/lubancat_sysroot/

-e "ssh -p 2222":指定 SSH 端口为 2222(对应 Windows 转发的端口);

root@<主机IP>:这里填步骤 3 获取的主机 IP(如 192.168.1.100),不是开发板 IP;

输入开发板 root 密码(鲁班猫默认root/lubancat),等待拷贝完成即可。
拷贝完有部分警告,可能是进程私有文件。/var下的 临时目录。

查看 sysroot下的核心系统目录,

bash 复制代码
ls -l ~/project/InfraredThermometer/lubancat_sysroot/ | grep -E "bin|etc|usr|lib|sbin|boot"
lrwxrwxrwx  1 root root    7 Oct 16 10:45 bin -> usr/bin
drwxr-xr-x  7 root root 4096 Jun 26  2025 boot
drwxrwxr-x 91 1001 1001 4096 Jun 26  2025 etc
lrwxrwxrwx  1 root root    7 Oct 16 10:45 lib -> usr/lib
lrwxrwxrwx  1 root root    8 Oct 16 10:45 sbin -> usr/sbin
drwxrwxr-x 11 1001 1001 4096 Jun 26  2025 usr
(base) teng@TengSea:~/project/InfraredThermometer$

创建docker镜像

bash 复制代码
cd ~/project/InfraredThermometer
cat > Dockerfile << EOF
FROM scratch
COPY lubancat_sysroot/ /
COPY --from=multiarch/qemu-user-static:latest /usr/bin/qemu-aarch64-static /usr/bin/
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WORKDIR /root
CMD ["/bin/bash"]
EOF

这个方法,试了一下, qemu拉取不下来,暂时不清楚是代理的问题还是镜像源的问题。

其实,开发板性能也够了,直接开发板上拉取根目录,在开发板上创建镜像,然后vscode继续后续开发,反而更方便。

直接开发板创建根文件目录

注意,rsync 使用 --exclude排除目录时,最好使用绝对路径。

测试了,./lubcancat_sysroot这种相对路径失效,拷贝时仍然陷入了无限递归。

更安全的做法是使用 df -h 判断文件夹是否与根目录不在同一分区。

不在同一分区的属于独立挂载点,rsync 不会深度遍历。

bash 复制代码
# 安装必要工具(用于打包sysroot)
sudo apt-get update && sudo apt-get install -y rsync

# 1. 先进入项目目录,提前创建空的lubancat_sysroot目录(明确目标目录,方便排除)
cd /home/cat/project/InfraredThermometer
mkdir -p lubancat_sysroot

# 2. 安全打包sysroot(明确排除目标目录+虚拟文件系统,无自循环风险)
sudo rsync -av \
  --exclude=/proc \          # 排除虚拟文件系统
  --exclude=/sys \
  --exclude=/tmp \
  --exclude=/var/tmp \
  --exclude=/opt/lubancat_sysroot_temp \  # 一定要使用绝对路径
  / \                        # 源目录:根目录
  /opt/lubancat_sysroot_temp/ # 目标目录:/opt下的独立目录(隔离项目目录)

拷贝完成后,把隔离目录下的 sysroot 移动到项目目录,不影响后续构建:

bash 复制代码
# 1. 进入项目目录
cd /home/cat/project/InfraredThermometer

# 2. 移动sysroot到项目目录(重命名为lubancat_sysroot,保持一致性)
mv /opt/lubancat_sysroot_temp ./lubancat_sysroot

# 3. (可选)删除/opt下的空目录,清理环境
sudo rm -rf /opt/lubancat_sysroot_temp

修改文件夹的权限,

bash 复制代码
sudo chown -R cat:cat lubancat_sysroot/
#            所有者:所属组

安装Docker

bash 复制代码
# 1. 安装Docker依赖
sudo apt-get update && sudo apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 2. 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 3. 添加Docker arm64软件源
echo \
  "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 4. 安装Docker Engine(纯arm64版本,适配开发板)
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# 5. 启动Docker并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 6. 给cat用户添加Docker权限(避免后续执行docker命令需要sudo)
sudo usermod -aG docker cat

执行完成后,关闭当前 VSCode 终端,

重新打开一个新终端(权限生效),

执行docker --version,输出 Docker 版本信息,说明安装成功。

编写Dockerfile

bash 复制代码
cat > Dockerfile << EOF
# 开发板是arm64架构,直接使用scratch空镜像(天然适配,无任何冗余)
FROM scratch

# 拷贝开发板本地的纯arm64 sysroot(和运行环境1:1一致,权限已改为cat,无需sudo)
COPY lubancat_sysroot/ /

# 配置系统环境变量,确保/bin、/usr/bin下的命令可正常执行(如gcc、ls等)
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# 配置项目工作目录(后续存放红外测温代码,和开发板项目目录挂载同步)
WORKDIR /root/InfraredThermometer

# 容器启动默认进入bash终端,方便编译、调试代码
CMD ["/bin/bash"]
EOF

lubancat-debian运行Docker-ce失败

问题层级 具体原因 对应实操报错 / 现象 可修复性
核心底层原因 Cgroup 控制组不兼容:系统为简化版 Cgroup v1(裁剪高级功能),且挂载路径非标准,Docker 无法识别 / 使用 Job for docker.service failedsystemctl status 显示 cgroup 相关初始化错误 ❌ 无法简单修复 (需深度定制系统)
核心底层原因 Docker Daemon 与嵌入式系统设计不匹配:Daemon 为桌面 / 服务器设计,依赖完整系统功能,嵌入式系统无法稳定支撑 Docker 服务启动超时 / 崩溃; 无明确报错但 daemon 进程无法常驻 ❌ 无法简单修复 (需重构系统服务逻辑)
定制系统专属原因 Rockchip 硬件服务资源抢占:rockchip.sh / rkbt.sh 等脚本独占 Cgroup / 硬件挂载权限,与 Docker 冲突 安装时提示 insserv: script rockchip.sh: service rockchip already provided!; Docker 启动失败 ❌ 无法规避 (禁用脚本会丢失红外 / GPIO 等硬件功能)
表层前期问题 Docker 官方国外源 IPv6 访问失败:网络环境不支持 IPv6,源解析 / SSL 握手失败 curl: (35) OpenSSL SSL_connect: Connection reset by peerCould not handshake ✅ 易修复 (换国内源 + 临时禁用 IPv6)
表层前期问题 发行版配置混淆:误将 Ubuntu 的 Docker 源 / GPG 密钥配置套用在 Debian 系统上 gpg: no valid OpenPGP data found.; 源配置无效,无 Docker 安装候选 ✅ 易修复 (清理无效配置 + 匹配 Debian 专属配置)
辅助加剧原因 嵌入式硬件资源有限:Docker Daemon 占用内存 / 存储,与硬件驱动服务争夺资源 Docker 启动时提示 out of memory; 进程意外崩溃 ⚠️ 难以优化 (嵌入式硬件固有属性)
辅助加剧原因 系统功能裁剪:定制 Debian 为省资源,裁剪了 Docker 所需的部分非核心系统功能 Docker Daemon 初始化时提示「功能缺失 / 文件找不到」; 无明确报错但服务无法启动 ⚠️ 难以优化 (裁剪功能与硬件兼容性强绑定)

Cgroup是什么

Cgroup(Control Group,控制组)是 Linux 内核的一项核心功能,用于限制、记录和隔离进程组的资源使用(CPU、内存、磁盘 I/O、网络等)。

bash 复制代码
┌─────────────────────────────────────────┐
│           Linux 系统(所有进程)            │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ 进程 A  │  │ 进程 B  │  │ 进程 C  │  │
│  │ (Web)   │  │ (DB)    │  │ (日志)   │  │
│  └────┬────┘  └────┬────┘  └────┬────┘ │
│       └─────────────┴─────────────┘     │
│              Cgroup 层级结构              │
│  ┌─────────────────────────────────────┐ │
│  │  Cgroup: docker(CPU 限制 50%)       │ │
│  │   ├── 容器 1(内存限制 512MB)         │ │
│  │   └── 容器 2(内存限制 1GB)           │ │
│  └─────────────────────────────────────┘ │
│  ┌─────────────────────────────────────┐ │
│  │  Cgroup: system(保留 30% CPU)       │ │
│  │   ├── 系统服务                         │ │
│  │   └── Rockchip 硬件脚本                │ │
│  └─────────────────────────────────────┘ │
└─────────────────────────────────────────┘
特性 Cgroup v1 Cgroup v2
设计 多层级分离(cpu/memory/blkio 各自独立) 统一层级(所有控制器挂载到单一层级)
复杂度 复杂,各控制器路径不同 简化,统一路径 /sys/fs/cgroup
功能 功能完整但混乱 更严格的资源隔离,支持 delegation
Docker 支持 传统支持,但需完整功能 推荐版本,但需内核完整支持
嵌入式裁剪 常被裁剪部分控制器 需完整内核支持,裁剪后无法使用

podman替代docker?

Podman 是一个开源的容器管理工具,核心功能是创建、运行、管理和分发容器。

这个东西还没测试过。留个坑。

特性 Podman Docker
架构 无守护进程(直接 fork 子进程) 依赖 dockerd 守护进程
权限 支持 rootless(普通用户运行) 默认需要 root 或 docker 组
安全 更安全的 fork/exec 模型 客户端-服务器模型,攻击面较大
兼容性 完全兼容 Docker CLI 和镜像(OCI 标准) 行业标准,生态最完善
Cgroup 依赖 rootless 模式不依赖系统 Cgroup 强依赖 Cgroup 进行资源限制
嵌入式适用性 ⭐⭐⭐ 更适合裁剪系统 ⭐⭐ 需要完整系统功能

关于 scratch镜像

前面看到的 FROM 指令,

拉取的基础镜像是 scratch ------ 它和你熟悉的 ubuntu:arm64、debian:11-arm64 这类常规镜像完全不同,不是一个 "需要从 Docker Hub 拉取" 的带完整文件系统的镜像,

而是 Docker 官方提供的 **「空镜像」(也叫最小基础镜像)**,本身不包含任何文件、目录或预装工具,体积为 0。

已经从开发板拷贝了完整的 sysroot(包含开发板原生的 arm64 文件系统、系统库、配置文件、内核依赖等),scratch 作为空镜像,正好可以直接将这份 sysroot 完整拷贝进去,形成一个和开发板原生环境完全一致的镜像。

而如果选择 ubuntu:22.04-arm64 这类常规镜像,它的文件系统、库版本、系统配置和鲁班猫 RK3588 的原生系统可能存在差异(比如开发板是定制化 Debian,和官方 Ubuntu 的库版本不一致),会导致安装的第三方库出现兼容问题,违背你 "确保镜像和开发板环境一致" 的核心诉求。

关于 QEMU的拉取

qemu-aarch64-static 就像一个「架构翻译官」:

当 Docker 在构建过程中,需要执行镜像内的 arm64 命令时(比如拷贝完 sysroot 后,执行 arm64 版本的 apt-get),qemu 会后台介入,把 arm64 命令「翻译」成 x86 引擎能识别的指令,执行完成后,再把结果转回 arm64 格式,存入镜像。

docker不自带 qemu,因此 dockerfile执行的时候拉取。

qemu 是一款成熟的开源跨架构模拟工具,早于 Docker 存在,Docker 并没有必要重新开发一套类似功能,而是提供了和 qemu 的「协作接口」------ 让 Docker 在需要跨架构构建 / 运行时,能够调用外部的 qemu 工具。

关于 QEMU的必要性

我的需求是,

镜像内的「文件 / 库 / 程序」全是arm64架构(迁移到开发板可直接用),无关 PC 是否能运行这个镜像。

让 x86 PC 上的 Docker,在「构建 arm64 镜像的过程中」,能够执行 arm64 架构的系统命令(如apt-get install、make等),从而确保安装的第三方库、编译的产物都是arm64架构,这是制作纯 arm64 镜像的关键,且这个过程中 qemu 是「后台辅助工具」,你无需感知它的运行。

qemu是 pc能够运行 arm架构的基础。

怎么判断/opt或/mnt与根目录隔离

其实也不一定隔离,

bash 复制代码
cat@lubancat:/opt/lubancat_sysroot_temp$ df -h /opt
Filesystem      Size  Used Avail Use% Mounted on
/dev/mmcblk0p3   58G  4.7G   51G   9% /
cat@lubancat:/opt/lubancat_sysroot_temp$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/mmcblk0p3   58G  4.7G   51G   9% /
cat@lubancat:/opt/lubancat_sysroot_temp$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/mmcblk0p3   58G  4.7G   51G   9% /

三者都是同一个分区 /dev/mmcblk0p3,没有独立挂载点。

所以是用的绝对路径,排除了目标文件夹。

相关推荐
感觉不怎么会2 小时前
Android 13 - 对讲app后台休眠后无法录音
android·linux
程序 代码狂人2 小时前
CentOS7中有趣的yum源(彩蛋)-----第二期
linux·运维·服务器
Y‍waiX‍‍‮‪‎⁠‌‫‎‌‫‬2 小时前
CentOS7(Linux)从系统安装到环境搭建
linux·运维·服务器
码界奇点2 小时前
基于eBPF技术的高性能网络防火墙系统设计与实现
开发语言·网络·毕业设计·php·wpf·go语言·源代码管理
sunlifenger2 小时前
【兆越课堂】时间的回归|网络“同步性”的进化简史
网络·5g·信息与通信
蒹葭玉树2 小时前
【C++上岸】C++常见面试题目--网络篇(第二十六期)
网络·c++·面试
若风的雨2 小时前
【 ARMv8多核处理器启动方案设计】
linux·arm开发
七夜zippoe3 小时前
WebSocket实时通信系统构建:从握手协议到生产级实战
网络·python·websocket·网络协议·心跳
玉树临风江流儿3 小时前
linux使用 nmcli工具扫描、连接WiFi
网络