1. 项目背景与核心需求
最近在折腾一个嵌入式视频监控项目,需要让设备支持ONVIF协议。ONVIF作为安防领域的通用协议栈,其实现涉及多个组件,其中onvif_srvd和wsdd这两个开源组件尤为关键。前者负责实现ONVIF设备服务端功能,后者则处理WS-Discovery服务发现机制。但在实际编译过程中,发现网上能找到的完整编译指南寥寥无几,大多都是零散的代码片段。于是决定把整个编译过程记录下来,给后来者铺条路。
这个编译过程主要解决三个核心问题:一是处理开源组件间的版本依赖关系,二是解决交叉编译环境下的工具链适配问题,三是配置服务参数使其符合ONVIF规范要求。整个过程涉及Makefile修改、库文件链接、服务注册等多个技术环节,对嵌入式Linux开发具有典型参考价值。
2. 环境准备与工具链配置
2.1 基础环境搭建
我的开发环境是Ubuntu 20.04 LTS,目标设备是ARM架构的嵌入式Linux板。首先需要安装基础编译工具:
bash复制sudo apt install build-essential cmake git autoconf libtool
特别注意:如果目标设备是嵌入式平台,必须提前准备好对应的交叉编译工具链。我使用的是arm-linux-gnueabihf-gcc 9.3.0版本,工具链路径需要正确配置到PATH环境变量中:
bash复制export PATH=/opt/toolchain/arm-linux-gnueabihf/bin:$PATH
2.2 依赖库安装
onvif_srvd依赖以下几个关键库:
- libssl-dev(TLS加密支持)
- libxml2-dev(XML解析)
- libgsoap-dev(SOAP协议栈)
安装命令如下:
bash复制sudo apt install libssl-dev libxml2-dev libgsoap-2.8.91
这里有个坑点:不同Linux发行版的gSOAP包名可能不同。Ubuntu下是libgsoap-2.8.91,而某些版本可能叫libgsoap2.8。如果遇到找不到包的情况,建议直接从源码编译gSOAP:
bash复制wget https://sourceforge.net/projects/gsoap2/files/gsoap-2.8/gsoap_2.8.91.zip
unzip gsoap_2.8.91.zip
cd gsoap-2.8
./configure --prefix=/usr/local
make -j$(nproc)
sudo make install
3. onvif_srvd编译详解
3.1 源码获取与准备
从GitHub获取最新源码:
bash复制git clone https://github.com/agsh/onvif_srvd.git
cd onvif_srvd
这个仓库包含两个关键组件:
- onvif_srvd:主服务程序
- wsdd:发现服务程序
3.2 交叉编译配置
修改Makefile是关键步骤。主要调整点包括:
- 指定交叉编译器:
makefile复制CC = arm-linux-gnueabihf-gcc
- 调整编译选项:
makefile复制CFLAGS += -Os -Wall -Wextra -I/usr/local/include
LDFLAGS += -L/usr/local/lib -lssl -lcrypto -lpthread -lgsoap
- 处理库文件路径:
makefile复制LIBS = -lssl -lcrypto -lgsoap -lpthread
特别注意:如果目标设备有特殊的库路径,需要通过LDFLAGS指定运行时库路径:
makefile复制LDFLAGS += -Wl,-rpath=/usr/local/lib
3.3 编译过程实录
执行编译命令:
bash复制make clean
make -j$(nproc)
常见问题及解决方案:
-
报错:找不到gsoap/soap.h
原因:gSOAP头文件路径未正确包含
解决:检查CFLAGS中的-I参数是否包含gSOAP头文件路径 -
链接错误:undefined reference to 'soap_ssl_init'
原因:gSOAP版本不匹配
解决:确保使用的gSOAP版本≥2.8.91,建议从源码重新编译安装 -
段错误(segmentation fault)
原因:ARM架构对齐问题
解决:在CFLAGS中添加-mno-unaligned-access
4. wsdd服务编译与配置
4.1 服务发现机制解析
wsdd实现WS-Discovery协议,主要功能包括:
- 响应网络探测请求
- 定期发送Hello消息
- 处理Bye消息注销服务
其通信基于UDP多播,默认使用3702端口。与onvif_srvd的关系如下图所示:
| 组件 | 协议 | 端口 | 功能 |
|---|---|---|---|
| onvif_srvd | HTTP | 8080 | 提供ONVIF设备服务 |
| wsdd | UDP | 3702 | 服务发现与设备通告 |
4.2 编译参数调整
wsdd的Makefile需要特别关注以下参数:
makefile复制CFLAGS += -DDEBUG -DNO_IPV6
其中:
-DDEBUG:启用调试日志(生产环境应移除)-DNO_IPV6:禁用IPv6支持(根据实际需求选择)
4.3 服务集成测试
编译完成后,将生成的可执行文件传输到目标设备进行测试:
bash复制scp onvif_srvd wsdd root@target:/usr/local/bin/
在目标设备上启动服务:
bash复制./wsdd &
./onvif_srvd -i eth0 -f /etc/onvif.conf
关键参数说明:
-i:指定网络接口-f:配置文件路径(需提前准备)
5. 配置文件与参数优化
5.1 onvif.conf配置详解
配置文件示例:
xml复制<onvif>
<server>
<port>8080</port>
<ssl>0</ssl>
</server>
<device>
<manufacturer>MyCompany</manufacturer>
<model>IPC-100</model>
<firmware>v1.0.0</firmware>
</device>
</onvif>
关键参数说明:
ssl:是否启用HTTPS(需要额外配置证书)manufacturer/model:必须符合ONVIF规范命名
5.2 性能调优建议
-
内存优化:
在嵌入式设备上,可以通过修改gSOAP内存池大小来降低内存占用:c复制#define SOAP_MEM_BLK_SIZE 4096 // 默认8192 -
线程配置:
onvif_srvd默认使用多线程模式,在低端设备上可以改为单线程:bash复制
./onvif_srvd -m 1 -
日志控制:
通过编译选项控制日志级别:makefile复制
CFLAGS += -DLOG_LEVEL=3 // 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG
6. 常见问题排查指南
6.1 服务无法被发现
排查步骤:
-
检查wsdd是否正常运行:
bash复制
netstat -anu | grep 3702 -
验证多播通信:
bash复制
tcpdump -i eth0 port 3702 -
检查防火墙规则:
bash复制
iptables -L -n | grep 3702
6.2 设备信息不显示
可能原因:
- 配置文件路径错误
- XML格式不正确
- 设备信息字段缺失
解决方法:
- 使用
-v参数启动onvif_srvd查看详细日志 - 检查配置文件权限(需可读)
- 验证XML格式(可用xmllint工具)
6.3 高CPU占用问题
优化方案:
-
调整wsdd的广播间隔(默认30秒):
bash复制./wsdd -i 60 # 改为60秒 -
限制客户端连接数:
bash复制./onvif_srvd -c 10 # 最大10个连接 -
关闭不必要的服务:
在配置文件中注释掉不用的功能模块
7. 实际部署建议
7.1 系统集成方案
建议将服务集成到系统启动流程中,创建systemd服务文件:
ini复制[Unit]
Description=ONVIF Service
After=network.target
[Service]
ExecStart=/usr/local/bin/wsdd
ExecStartPost=/usr/local/bin/onvif_srvd -f /etc/onvif.conf
Restart=always
[Install]
WantedBy=multi-user.target
7.2 安全加固措施
-
通信加密:
启用HTTPS需要准备:- 有效的SSL证书
- 修改配置中的ssl参数为1
- 指定证书路径
-
访问控制:
通过iptables限制访问IP:bash复制
iptables -A INPUT -p tcp --dport 8080 -s 192.168.1.0/24 -j ACCEPT -
服务隔离:
建议使用非root用户运行服务:bash复制useradd -r onvif chown onvif:onvif /usr/local/bin/onvif_srvd
8. 进阶开发指导
8.1 功能扩展建议
如果需要添加自定义功能,可以修改以下关键文件:
service.c:实现新的ONVIF服务onvif.h:定义服务接口soap_*.c:gSOAP生成的桩代码
典型开发流程:
- 修改ONVIF WSDL定义
- 使用gSOAP重新生成代码框架
- 实现具体的服务逻辑
8.2 性能监控方案
建议集成以下监控指标:
-
服务可用性:
bash复制curl -s http://localhost:8080/onvif/device_service | grep -q "Device" -
资源占用:
bash复制
ps -o %cpu,%mem -C onvif_srvd -
网络流量:
bash复制iftop -i eth0 -f "port 8080 or port 3702"
在嵌入式设备上实际运行半年后,发现内存泄漏主要发生在gSOAP的XML解析环节。通过定期重启服务(每周一次)可以有效控制内存增长。另外,将日志级别设置为WARN后,CPU负载从15%降至8%,说明日志输出对性能影响显著。