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 failed; systemctl 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 peer; Could 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,没有独立挂载点。
所以是用的绝对路径,排除了目标文件夹。