如何在OpenWrt软路由中增加一个新功能

📅 2026/7/23 18:24:50
如何在OpenWrt软路由中增加一个新功能
为了在OpenWrt中增加一个新的功能并使其支持 UCI 配置我们可以创建一个简单的C语言服务例如一个简单的日志服务。此服务将记录到日志文件中并支持通过 UCI 配置启用或禁用日志功能。以下是详细的步骤和代码示例。1 创建服务代码1.1 创建服务的源代码 (logservice.c)这个服务将检查 UCI 配置根据配置决定是否写入日志c #include stdio.h #include stdlib.h #include unistd.h #include uci.h void log_message(const char *message) { FILE *file fopen(/tmp/logservice.log, a); if (file) { fprintf(file, %s\n, message); fclose(file); } } int main(void) { struct uci_context *c; struct uci_ptr ptr; char *enabled; c uci_alloc_context(); if (uci_lookup_ptr(c, ptr, logservice.global.enabled, true) UCI_OK) { enabled ptr.o-v.string; if (strcmp(enabled, 1) 0) { while (1) { log_message(Log service is active.); sleep(60); // Log every minute } } } uci_free_context(c); return 0; }1.2 创建 Makefile来编译这个服务makefile CCgcc CFLAGS-I. DEPS uci.h OBJ logservice.o %.o: %.c $(DEPS) $(CC) -c -o $ $ $(CFLAGS) logservice: $(OBJ) $(CC) -o $ $^ $(CFLAGS) -luci clean: rm -f *.o logservice2 为 OpenWrt 创建软件包2.1 创建 OpenWrt 包目录结构在 OpenWrt 构建环境中的 package 目录下创建一个新目录 logservice。mkdir -p package/logservice cd package/logservice2.2 创建控制文件(Makefile)这个文件定义了包的元数据和如何编译和安装它makefile include $(TOPDIR)/rules.mk PKG_NAME:logservice PKG_RELEASE:1 PKG_VERSION:1.0.0 include $(INCLUDE_DIR)/package.mk define Package/logservice SECTION:utils CATEGORY:Utilities TITLE:Simple Log Service DEPENDS:libuci endef define Package/logservice/description A simple service that logs messages to a file based on UCI configuration. endef define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef define Build/Compile $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) endef define Package/logservice/install $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_BIN) $(PKG_BUILD_DIR)/logservice $(1)/usr/sbin/ $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/logservice.init $(1)/etc/init.d/logservice $(INSTALL_DIR) $(1)/etc/config $(INSTALL_DATA) ./files/logservice.config $(1)/etc/config/logservice endef $(eval $(call BuildPackage,logservice))控制文件通常指的是用于描述和控制软件包编译和安装过程的 Makefile。这个 Makefile 与传统的 Linux/Unix 系统中用于编译程序的 Makefile 相似但它专门为 OpenWrt 的包管理系统设计用来定义软件包的元数据、构建和安装行为。通常包含以下部分包的定义和元数据PKG_NAME定义软件包的名称。PKG_VERSION定义软件包的版本号。PKG_RELEASE软件包的发布次数通常用于修订号或当相同版本号的包被修改时递增。PKG_SOURCE、PKG_SOURCE_URL、PKG_HASH可选定义软件包源代码的位置、下载 URL 和源码的哈希值用于验证。包含 OpenWrt 构建系统的规则和宏定义include $(TOPDIR)/rules.mk包含了 OpenWrt 主目录下的通用规则文件。include $(INCLUDE_DIR)/package.mk包含处理软件包的核心功能和定义的文件。软件包定义区域define Package/开始定义一个软件包其中 是软件包的名称通常与 PKG_NAME 相同。SECTION、CATEGORY软件包的分类和子分类。TITLE软件包的简短描述或标题。DEPENDS定义软件包的依赖如依赖其他库或软件包。包描述define Package//description提供软件包的详细描述。准备构建环境define Build/Prepare准备构建目录通常包括解压源码、应用补丁等步骤。配置软件包define Build/Configure可选如果软件包需要特殊的配置步骤可以在这里定义。编译软件包define Build/Compile定义编译软件包的命令和步骤。安装软件包define Package//install定义如何安装编译后的软件到目标目录通常包括拷贝可执行文件、配置文件等到相应的安装目录。注册软件包$(eval $(call BuildPackage,))这是一个宏调用用于注册软件包使得构建系统能够识别和处理它。2.3 创建 UCI 配置文件和初始化脚本UCI 配置(logservice.config):config logservice global option enabled 1初始化脚本(logservice.init):#!/bin/sh /etc/rc.common START99 start() { /usr/sbin/logservice } stop() { killall logservice }在 OpenWrt 或其他使用 init.d 脚本的 Unix-like 系统中logservice.init 脚本的作用是控制 logservice 服务的启动、停止以及其他管理操作。这个脚本通常被称为 init 脚本或服务脚本并且是服务管理的核心组成部分。logservice.init 脚本主要提供以下功能启动服务start当系统启动或手动启动服务时该脚本将被调用以启动 logservice 程序。通常这涉及到运行主服务程序并可能还包括设置必要的环境或运行前的配置。停止服务stop当系统关闭或需要手动停止服务时该脚本用于安全地停止 logservice 程序。这通常涉及到发送终止信号给服务进程或执行其他清理步骤。重启服务restart这通常是通过停止后再启动服务来实现有时是为了应用新的配置更改或恢复服务的正常状态。查看服务状态status尽管在给出的脚本示例中没有直接实现但许多服务脚本还支持检查并报告服务是否正在运行以及运行状态。启动顺序START在 logservice.init 脚本中定义的 START99 表示此服务在系统启动过程中的启动顺序。数值越大启动越晚允许它在其他服务之后启动。logservice.init 脚本是服务生命周期管理的关键工具它允许系统管理员和系统本身在适当的时间以适当的方式启动和停止服务。在 OpenWrt 这样的嵌入式系统中这种脚本是管理后台服务不可或缺的部分确保了服务的可控性和稳定性。3 编译和安装将软件包添加到 OpenWrt 构建系统返回到 OpenWrt 的根目录并运行 make menuconfig。在 Utilities 菜单下选择 logservice 包进行编译。编译 OpenWrt 镜像make package/logservice/compile Vsmake Vs刷写固件并测试服务安装生成的固件到你的设备上并测试 logservice 是否根据 UCI 配置正确运行。这个例子展示了如何为 OpenWrt 添加一个简单的 C 语言编写的服务使其支持 UCI 配置。4 OpenWrt NFC功能的例子代码包括两个部分一个是 OpenWrt 的启动脚本用于管理 NFC 服务的启动和停止另一个是 Makefile用于编译 NFC 相关的 C 代码。4.1 启动脚本init.d解释#!/bin/sh /etc/rc.commonUSE_PROCD1START46STOP99SERVICE_USE_PID1USE_PROCD1PROG/usr/bin/topsw_nfc这是一个 shell 脚本用于控制 NFC 服务 (topsw_nfc) 的启动和停止。USE_PROCD1启用 procd 支持procd 是 OpenWrt 的进程管理守护程序。START46和STOP99定义了服务启动和停止的优先级。数字越小启动优先级越高停止时则相反。SERVICE_USE_PID1表明该服务使用 PID 文件。PROG/usr/bin/topsw_nfc定义了 NFC 程序的路径。start_service(){procd_open_instance procd_set_param stdout1procd_set_param stderr1procd_set_paramcommand$PROGprocd_set_param respawn procd_close_instance}start_service函数用于配置和启动服务。procd_open_instance开启一个新的服务实例。procd_set_param设置服务参数如标准输出、错误输出、启动命令和重启参数。procd_close_instance关闭实例配置启动服务。reload_service(){restart}reload_service定义重启服务的功能使用restart命令重启服务。4.2 Makefile解释PROGS topsw_nfc定义要编译的程序名称。SOURCES $(wildcard ./src/*.c) OBJS $(patsubst %.c,%.o,$(SOURCES))SOURCES获取src目录下所有的.c文件。OBJS将源文件名从.c转换为.o。$(OBJS): %.o : %.c $(CC) -c $(CFLAGS) $(CFLAGS) $^ -o $规则说明如何从.c文件生成.o文件。$(PROGS): $(OBJS)最终链接生成可执行文件的规则。4.3 NFC添加到系统中的步骤编译使用 Makefile 编译 NFC 相关的 C 代码生成可执行文件topsw_nfc。部署将编译好的程序部署到/usr/bin/topsw_nfc路径下。服务管理通过 OpenWrt 的启动脚本管理 NFC 服务的启动、停止和重启配置启动配置脚本确保在系统启动时NFC 服务按指定的优先级启动并在停止时按相反的优先级停止。在 OpenWrt 及类似的构建系统中系统能够知道存在topsw_nfc这个包并允许在图形界面中进行选择主要是通过以下几个关键步骤实现的包定义文件Makefile每个可选的软件包在 OpenWrt 的源代码目录中通常都有一个对应的包定义文件即一个 Makefile。这个 Makefile 不仅定义了如何下载、配置、编译、安装、清理该软件包还包含了软件包的描述、依赖关系和配置选项等元数据。包目录结构在 OpenWrt 的源代码中通常有一个package目录其中每个子目录或文件夹代表一个包。例如topsw_nfc包可能位于package/network/services/topsw_nfc目录下。Makefile 内容此 Makefile 将包含如下关键信息Package定义用于设置包名和描述。define Package/topsw_nfc其中包括描述、版本、分类等。编译和安装指令指明如何构建和安装包。可能还包括Config.in或config段落用于定义配置界面中的选项。配置系统集成OpenWrt 使用 Kconfig 系统这是从 Linux 内核借鉴的配置工具用于在图形界面 (make menuconfig) 中显示和选择配置选项。Kconfig 与 Makefile包的 Makefile 中通常包括指向 Kconfig 文件的引用这使得构建系统在运行make menuconfig时可以解析并显示所有可用的包选项。配置选项在 Kconfig 文件或 Makefile 中定义的配置选项决定了包是否可以被选中以及它依赖哪些条件。图形界面中的显示当运行make menuconfig时OpenWrt 的构建系统会扫描所有包的 Makefile 和 Kconfig 文件将它们的信息汇总到配置界面中。用户交互在图形界面中用户可以浏览各种类别的软件包选择需要编译进固件的包。依赖解析如果topsw_nfc包依赖其他库或包这些依赖也会在图形界面中显示用户必须先解决依赖问题才能启用该包。系统的响应选择了topsw_nfc包并保存配置后这些选择被写入.config文件这是构建系统在后续构建过程中读取的配置文件。总结来说系统通过预定义的包描述文件Makefile、Kconfig 集成以及图形配置界面menuconfig相结合的方式使得用户可以选择特定的软件包如topsw_nfc进行编译和安装。这种方法保证了构建系统的灵活性和可扩展性允许用户根据需要定制自己的固件。