OpenWrt 入门:从源码构建自己的固件(NanoPi R5S 为例)

OpenWrt 入门:从源码构建自己的固件(NanoPi R5S 为例)

前言

自不久前 OpenWrt 正式发布 24.10 版本以来,我一直想找个机会将手头的 NanoPi R5S 适配到该版本。近期我终于抽空从零开始构建了一次 OpenWrt,主要是为设备减轻适配负担(旧方案历史包袱过多),也是为本文创造素材。

本文是从源代码制作 OpenWrt 固件的方法,包含构建的基本流程、菜单配置、软件包定制、优化等内容。这是一篇新手向教程,内容繁多但过程简单!

准备工作

设备的基本要求:

系统:Ubuntu 24.04

较多核心的 CPU 和较大的内存!

畅通的网络(如无障碍访问 GitHub)

尽量掌握的技能:

命令行的最基本使用

Git 的最基本使用

安装依赖

在 Ubuntu 24.04 系统上,安装以下依赖:

sudo apt install -y \

build-essential \

ccache \

ecj \

fastjar \

file \

g++ \

gawk \

gettext \

git \

java-propose-classpath \

libelf-dev \

libncurses5-dev \

libncursesw5-dev \

libssl-dev \

unzip \

wget \

python3 \

python3-dev \

python3-setuptools \

python3-pyelftools \

rsync \

subversion \

swig \

time \

xsltproc \

zlib1g-dev \

clang \

golang \

llvm

如果你的系统长久未更新,请先执行 apt update 更新系统。

快速开始

确保环境已准备好。以下将经过一系列十分简洁的步骤,快速构建出第一个可用镜像!

克隆代码

首先我们需要拉取源代码,才能开始后续操作。执行 Git 命令:

git clone https://github.com/openwrt/openwrt.git -b openwrt-24.10 --depth 1

在以上命令中,我们拉取了 OpenWrt 官方仓库 openwrt-24.10 分支的最新代码。其中 -b 参数指定此次克隆的是 openwrt-24.10 分支,--depth 1 表示仅拉取最新的一次提交,无历史记录(避免仓库过大耽误时间)。

更新/安装 feeds

进入 openwrt 目录,执行命令:

./scripts/feeds update -a && ./scripts/feeds install -a

等待 feeds 的更新和安装,全部完成后就可以开始配置了。

菜单配置

执行 make menuconfig 打开构建菜单。菜单配置的基本使用:

方向键和 Tab 键移动焦点

回车进入子菜单

空格切换选择状态(<*> / [*]、 / [M]、< > / [ ] 和 (X)、( ) 等)

本文以 NanoPi R5S 为例,24.10 的官方代码已经适配了此设备。我们直接选择对应的 profile 即可。步骤如下:

进入 Target System --->,勾选 <*> Rockchip

进入 Subtarget --->,勾选 <*> RK33xx/RK35xx boards (64 bit)

进入 Target Profile --->,勾选 <*> FriendlyARM NanoPi R5S

其它设备请通过 OpenWrt 的 Supported devices 页面寻找对应的 profile。

完成以上三个配置后,应该是这个样子的:

留意箭头的位置,它应该对应你的设备的全名(品牌 + 型号)。

实际上我们现在就已经可以开始构建了!但是为了更直观的看出配置的简单性,我们进一步探索一下。

执行如下命令生成 diffconfig:

./scripts/diffconfig.sh > diffconfig

查看 diffconfig 文件,内容如下:

CONFIG_TARGET_rockchip=y

CONFIG_TARGET_rockchip_armv8=y

CONFIG_TARGET_rockchip_armv8_DEVICE_friendlyarm_nanopi-r5s=y

嗯,最简单的配置就是这么简洁。后续的任何新增修改,都可以导入 diffconfig。通过此文件迁移/恢复菜单配置。

构建

现在,开始第一次构建!执行如下命令:

make -j$(nproc) || { make -j1 V=s; }

有一些教程会告诉你先执行 make -j$(nproc),如果出错了就执行 make -j1 V=s。而以上命令的含义就是,当前者执行失败后,自动执行后者。

过程可能会比较漫长。如果是笔记本电脑,可能要几个小时。在我的台式电脑上,全新的构建大约 40 分钟左右。

构建输出在 bin/targets 目录,目录树如下:

bin/targets/

└── rockchip

└── armv8

├── config.buildinfo

├── feeds.buildinfo

├── openwrt-rockchip-armv8-friendlyarm_nanopi-r5s-ext4-sysupgrade.img.gz

├── openwrt-rockchip-armv8-friendlyarm_nanopi-r5s.manifest

├── openwrt-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img.gz

├── packages

├── profiles.json

├── sha256sums

└── version.buildinfo

4 directories, 8 files

可以看到我们的固件在 rockchip/armv8 目录,该目录生成文件大小如下:

4.00 KiB config.buildinfo

4.00 KiB feeds.buildinfo

4.00 KiB openwrt-rockchip-armv8-friendlyarm_nanopi-r5s.manifest

4.00 KiB profiles.json

4.00 KiB sha256sums

4.00 KiB version.buildinfo

1.03 MiB packages

8.14 MiB openwrt-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img.gz

8.91 MiB openwrt-rockchip-armv8-friendlyarm_nanopi-r5s-ext4-sysupgrade.img.gz

18.09 MiB total

这时候的固件体积还是很小的,不到 10MB。现在我们将 openwrt-rockchip-armv8-friendlyarm_nanopi-r5s-squashfs-sysupgrade.img.gz 文件通过 OpenWrt 的「系统」-「升级与备份」-「刷写固件」功能上传,即可将自己编译的固件刷入设备。

当然,刷入当前固件的意义并不大。通常我们的固件至少需要包含 LuCI,否则只能进行 SSH 命令操作。请从下一节开始,继续完善你的固件。至少完成 LuCI 基础包的配置,然后重新执行构建命令。结束后尝试将包含 LuCI 的固件刷入设备,现在访问路由器的 IP 地址应该可以看到页面了。

定制软件包

本章节是一些基础软件包和推荐软件包的配置方法,可以随意跳过没有先后和依赖关系。

切记每次完成配置后,使用底部的 < Save > 功能保存。以避免好不容易调整的配置丢失!

增加分区大小

如果在进行一定量的软件包添加后,构建发生下类错误:

ext4_allocate_best_fit_partial: failed to allocate 4996 blocks, out of space?

它提醒你调整根文件系统的分区大小。进入构建菜单中的 Target Images --->,修改 Root filesystem partition size (in MiB) 的值。当发送类似上述错误时,应该增大这个值(例如我将其设置为 1024)。

增加分区大小时不要超出路由器的实际可用空间。

LuCI

LuCI 是 OpenWrt 的 Web 管理界面,是许多功能的前端。基本上你没有理由拒绝安装它,除非你是极端的 SSH 命令行用户。

包含 LuCI 的基础包:

路径:LuCI --->,Collections --->

勾选:<*> luci

调整 LuCI 的默认语言为中文:

路径:LuCI --->,Modules --->,Translations --->

勾选:<*> Chinese Simplified (zh_Hans)

包含额外 LuCI 主题:

路径:LuCI --->,Themes --->

勾选:<*> luci-theme-material(我通常使用这个主题)

Docker

Docker 是最流行的容器化方案之一。通过 Docker 可以轻易部署很多服务端应用,而不用担心环境问题。使用 Docker 可以大幅度扩展 OpenWrt 的应用范围,不用顾及「有没有包」这种问题。

包含 Docker 基础包:

路径:Utilities --->

勾选:

<*> docker

<*> docker-compose

<*> dockerd --->

包含 LuCI 的 Docker 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-dockerman

可选增强功能:

返回到 <*> dockerd ---> 包的位置,回车进入子菜单,然后可以进一步启用一些可选功能了。例如 Overlay 网络驱动、对 Ext4/Ext3/Brafs 后备文件系统的支持等。

LXC

LXC 是另一个容器技术。和 Docker 不同它并非为部署单个应用进程而设计,它更像一个完整的虚拟机环境。使用 LXC 可以在 OpenWrt 这类简陋的嵌入式系统中体验各种传统 Linux 发行版(如 Ubuntu、Arch Linux、Void Linux 等),它们都比 OpenWrt 能做的多。

包含 LXC 基础包:

路径:Utilities --->

勾选:<*> lxc --->

包含必要的用户空间工具:

回车进入 <*> lxc ---> 子菜单

勾选:

<*> lxc-attach

<*> lxc-checkconfig

<*> lxc-config

<*> lxc-configs

<*> lxc-create

<*> lxc-destroy

<*> lxc-ls

<*> lxc-start

<*> lxc-stop

<*> lxc-templates

由于 R5S 空间充足,我勾选了全部的用户空间工具(lxc- 开头的包),并在 Configuration 中勾选了全部可选支持。

NFS

NFS 是 Linux 上常见的存储共享技术,在服务端应用更多。如果你有多个路由器,可以在路由器之间用 NFS 挂载彼此的远程目录,共享同一片存储。

包含必要的 NFS 包和配置:

路径:Network --->,Filesystems --->

勾选:

<*> nfs-kernel-server

<*> nfs-kernel-server-utils

Select nfs-kernel-server configuration options --->,[*] Include support for NFSv4

包含额外的 NFS 模块:

路径:Kernel modules --->,Filesystems --->

勾选:<*> kmod-fs-nfs-v3

Samba

Samba 是 SMB 的开源实现。相比于 NFS,Samba 更贴近普通用户,也更适合 Windows、Android 等操作系统。通常我们在内网共享文件,组建 NAS,主要使用 SMB 协议(Samba 服务端)。

包含必要的 Samba 软件包:

路径:Network --->

勾选:

<*> samba4-server

<*> samba4-utils

这里没有包含 Samba 的客户端(即 samba4-client),因为路由器通常是服务端角色。

包含 LuCI 的 Samba 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-samba4

DDNS

DDNS 即动态 DNS。它可以定期获取路由器变更的 IP,并自动更新 DNS 记录。让接入国内家庭宽带这类动态 IP 的路由器实现固定的域名访问。

包含必要的包:

路径:Network --->,IP Addresses and Names --->

勾选:

<*> ddns-scripts

<*> ddns-scripts-services

<*> ddns-scripts-utils

特定提供商支持,如 <*> ddns-scripts-cloudflare(Cloudflare)

包含 LuCI 的 DDNS 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-ddns

collectd

collectd 是一个用于收集系统各项指标数据的工具,以插件化的方式工作。以下勾选的插件从 CPU、硬盘等基本硬件到负载、DNS、交换空间等软件数据全面覆盖。

包含必要的包:

路径:Utilities --->

勾选:<*> collectd --->

包含必要的模块:

路径:Utilities --->,<*> collectd --->

勾选:

<*> collectd-mod-cpu

<*> collectd-mod-cpufreq

<*> collectd-mod-disk

<*> collectd-mod-dns

<*> collectd-mod-ethstat

<*> collectd-mod-interface

<*> collectd-mod-iptables

<*> collectd-mod-irq

<*> collectd-mod-iwinfo

<*> collectd-mod-load

<*> collectd-mod-memory

<*> collectd-mod-network

<*> collectd-mod-ping

<*> collectd-mod-rrdtool

<*> collectd-mod-sensors

<*> collectd-mod-swap

<*> collectd-mod-thermal

包含 LuCI 的 collectd 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-statistics

SQM

SQM 可以更智能的管理网络数据包队列(流量整形)。在高网络负载时,提升网络性能,有效避免网络堵塞和延迟升高。

包含必要的包:

路径:Base system --->,sqm-scripts --->

勾选:<*> sqm-scripts

包含 LuCI 的 sqm 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-sqm

QoS

QoS 是一种网络流量控制技术,可以根据不同的流量类型(如视频、游戏、下载等)进行优先级调整,以保证重要流量的传输质量。

包含必要的包:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-qos

vnstat2

vnstat2 是一个网络流量监控工具,可以监控网络流量的上传和下载情况。vnstati 用于生成流量统计图表。

包含必要的包:

路径:Network --->

勾选:

<*> vnstat2

<*> vnstati2

包含 LuCI 的 vnstat2 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-vnstat2

nlbwmon

nlbwmon 也是网络流量的监控工具。它通过 ARP 协议获取设备的 MAC 地址,然后通过 iptables 规则统计流量。可以十分精细的看到每个设备的流量情况。

包含必要的包:

路径:Network --->

勾选:<*> nlbwmon

包含 LuCI 的 nlbwmon 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-nlbwmon

frp

frp 是一个内网穿透工具,可以将内网服务映射到公网。例如你可以通过 frp 将路由器的 LuCI 界面映射到公网,方便远程管理。当然,你需要一个公网服务器作为 frp 服务端。

包含必要的包:

路径:Network --->,Web Servers/Proxies --->

勾选:<*> frpc

包含 LuCI 的 frpc 前端:

路径:LuCI --->,Applications --->

勾选:<*> luci-app-frpc

这里没有包含 frp 的服务端(即 frps),因为路由器通常是客户端的角色。

外部存储

如果你的路由器有 USB 接口,可以通过 USB 设备扩展路由器的存储空间。以下是 USB 挂载以及尽量通用的存储支持配置,包括对其它协议和各种文件系统支持。

包含必要的 USB 支持模块:

路径:Kernel modules --->,USB Support --->

勾选:

<*> kmod-usb-storage-extras

<*> kmod-usb-storage-uas

解释:UAS 是移动硬盘所使用的协议。虽然移动硬盘作为 USB 设备,但需要 UAS 协议支持才能使用。

包含必要的挂载工具包:

路径:Base system --->

勾选:<*> block-mount

包含必要的文件系统模块:

路径:Kernel modules --->,Filesystems --->

勾选:

<*> kmod-fs-btrfs

<*> kmod-fs-exfat

<*> kmod-fs-ext4

<*> kmod-fs-f2fs

<*> kmod-fs-ntfs3

<*> kmod-fs-vfat

解释:exfat/vfat 是 U 盘/SD 卡常用的文件系统。ext4/btrfs 是 Linux 上常用的文件系统。ntfs 是 Windows 上常用的文件系统。f2fs 是为移动设备闪存优化的文件系统,被 Android 推荐。

工具集

除了以上值得详细介绍的软件之外,还有很多工具也是我们在日常路由器维护、调试中会用到的,例如:

<*> blkid:查看块设备的 UUID

<*> curl:网络请求工具

<*> exfat-mkfs:exFAT 文件系统格式化工具

<*> f2fs-tools:f2fs 文件系统工具

<*> htop:系统负载查看工具

<*> hwinfo:硬件信息查看工具

<*> iperf3:网络性能测试工具

<*> ipset:IP 地址集管理工具

<*> jq:JSON 数据处理工具(用于在脚本中解析 API 响应数据)

<*> lsblk:列出块设备列表

<*> mount-utils:挂载工具集

<*> nano-full:nano 编辑器(小巧的终端编辑器)

<*> nstat:网络统计工具

<*> openssl-util:OpenSSL 工具集

<*> rclone:云存储同步工具

<*> rclone-config:rclone 配置工具

<*> screen:终端多路复用工具

<*> smartmontools:硬盘健康信息查看工具

<*> smartmontools-drivedb:smartmontools 驱动数据库

由于工具太多,此处不再列举具体路径。在菜单配置中可通过 / 搜索功能查找。

优化

TCP BBR

BBR 是 Google 研发的 TCP 拥塞控制算法,用于提高网络利用率。尤其在网络质量不佳造成拥堵的场景下,提升极为显著。

包含必要的内核模块:

路径:Kernel modules --->,Network Support --->

勾选:<*> kmod-tcp-bbr

zram

zram 是一个内核功能,可将一部分内存虚拟为具有实时压缩功能的交换块设备(/dev/zram*)。它可以取代传统的基于硬盘的 Swap(或同时存在),显著提升交换的速度。

虽然 zram 利用内存自身作为交互空间,但不是无意义的。因为 zram 可以实时压缩交换进去的数据,理论上可以容纳数倍于物理内存的数据(指解压后),具体取决于数据的可压缩性和压缩算法。

需要注意的是:zram 的压缩/解压缩过程会消耗一定的 CPU 资源。

包含必要的 zram 包:

路径:Base system --->

勾选:<*> zram-swap

包含必要的内核模块:

路径:Kernel modules --->,Other modules --->

勾选:<*> kmod-zram

调整 zram 的 compressor(压缩器):

路径:Base system --->,Other modules --->,ZRAM Default compressor --->

选择:(X) lz4(兼具速度和压缩率,适合性能不高的 ARM 设备)

默认情况下 OpenWrt 会使用物理内存的一半作为 zram 的交换空间。它可以和基于硬盘的 Swap 同时存在。

本章节还有一些内容,缓慢更新中……

结束语

这就是从源码构建实际可用的 OpenWrt 固件(及配置方法)的入门教程了。在 24.10 之前,本文举例的设备 R5S 实际上没有得到官方支持。它通过合并其它来源的补丁适配到 OpenWrt,更复杂和麻烦。但现在已经不需要了,所有的历史包袱(如过时补丁、版本限制)也不存在了。

由我构建和定制的 R5S 固件:Hentioe/OpenWrt-NanoPi-R5S-Builds。

相关文章

上海365彩票
问国六帝豪gt多少钱

问国六帝豪gt多少钱

📅 09-17 👀 7142
上海365彩票
21 款最佳 PC 离线/在线汽车驾驶游戏 [最新]
365取消提款
快手怎么横屏直播

快手怎么横屏直播

📅 09-09 👀 7140