為了在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
CC=gcc
CFLAGS=-I.
DEPS = uci.h
OBJ = logservice.o%.o: %.c $(DEPS)$(CC) -c -o $@ $< $(CFLAGS)logservice: $(OBJ)$(CC) -o $@ $^ $(CFLAGS) -luciclean:rm -f *.o logservice
2 為 OpenWrt 創建軟件包
2.1 創建 OpenWrt 包目錄結構
在 OpenWrt 構建環境中的 package 目錄下創建一個新目錄 logservice。
mkdir -p package/logservice
cd package/logservice
2.2 創建控制文件(Makefile)
這個文件定義了包的元數據和如何編譯和安裝它:
makefile
include $(TOPDIR)/rules.mkPKG_NAME:=logservice
PKG_RELEASE:=1
PKG_VERSION:=1.0.0include $(INCLUDE_DIR)/package.mkdefine Package/logserviceSECTION:=utilsCATEGORY:=UtilitiesTITLE:=Simple Log ServiceDEPENDS:=+libuci
endefdefine Package/logservice/descriptionA simple service that logs messages to a file based on UCI configuration.
endefdefine Build/Preparemkdir -p $(PKG_BUILD_DIR)$(CP) ./src/* $(PKG_BUILD_DIR)/
endefdefine Build/Compile$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endefdefine 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.commonSTART=99start() {/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 腳本中定義的 START=99 表示此服務在系統啟動過程中的啟動順序。數值越大,啟動越晚,允許它在其他服務之后啟動。
logservice.init 腳本是服務生命周期管理的關鍵工具,它允許系統管理員和系統本身在適當的時間以適當的方式啟動和停止服務。在 OpenWrt 這樣的嵌入式系統中,這種腳本是管理后臺服務不可或缺的部分,確保了服務的可控性和穩定性。
3 編譯和安裝
-
將軟件包添加到 OpenWrt 構建系統:
返回到 OpenWrt 的根目錄并運行 make menuconfig。在 Utilities 菜單下選擇 logservice 包進行編譯。
-
編譯 OpenWrt 鏡像:
make package/logservice/compile V=s
make V=s -
刷寫固件并測試服務:
安裝生成的固件到你的設備上,并測試 logservice 是否根據 UCI 配置正確運行。
這個例子展示了如何為 OpenWrt 添加一個簡單的 C 語言編寫的服務,使其支持 UCI 配置。
4 OpenWrt NFC功能的例子
代碼包括兩個部分:一個是 OpenWrt 的啟動腳本,用于管理 NFC 服務的啟動和停止;另一個是 Makefile,用于編譯 NFC 相關的 C 代碼。
4.1 啟動腳本init.d解釋
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=46
STOP=99
SERVICE_USE_PID=1
USE_PROCD=1
PROG=/usr/bin/topsw_nfc
- 這是一個 shell 腳本,用于控制 NFC 服務 (
topsw_nfc
) 的啟動和停止。 USE_PROCD=1
:啟用 procd 支持,procd 是 OpenWrt 的進程管理守護程序。START=46
和STOP=99
:定義了服務啟動和停止的優先級。數字越小,啟動優先級越高;停止時則相反。SERVICE_USE_PID=1
:表明該服務使用 PID 文件。PROG=/usr/bin/topsw_nfc
:定義了 NFC 程序的路徑。
start_service() {procd_open_instanceprocd_set_param stdout 1procd_set_param stderr 1procd_set_param command "$PROG"procd_set_param respawnprocd_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
,進行編譯和安裝。這種方法保證了構建系統的靈活性和可擴展性,允許用戶根據需要定制自己的固件。