百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

物联网开发|编译MQTT库mosquitto遇到版本问题(提供补丁)

lipiwang 2024-10-16 13:09 12 浏览 0 评论

1. 下达任务

领导:“你对物联网领域mqtt熟悉吗?其他项目组需要你帮忙。”

面试不都会被问到某技术栈的熟练程度吗,怎么说我以前还看过MQTT的官方文档,也用过mosquitto跑过例程,相对于“API调用者”略知一二。

我厚着脸皮说:“多少了解点。”

项目组白蔡解释:“公司和招标称为某新能源汽车厂商,咱们开发子系统接入汽车网络,业务需要用到MQTT协议,公司初定的第三方库有mosquitto和QT的MQTT库,不过两个库的环境都没搭建好”。

我问白蔡:“我只用过libmosquitto.so,跑过几个demo,它符合你们的业务要求吗?”

领导:“哈哈~早应该把任务派发到你这来,搭建环境就交给你了。”

白蔡捂着脸:“能用就行,挑剔个什么,曾今尝试编译mosquitto,但没成功。”

编译开源程序那还不是 有双手就行 的吗,我说:“不就是依赖第三方库比较多吗,源码都下载下来,累是累了点,应该问题不大吧。”

2. 还真不一定有手就行

期初我没打算手动组个下载第三方库,毫无技术含量还累人,打算用buildroot自动构建mosquitto依赖关系,最终生成的文件系统也能正常运行MQTT业务。只不过buildroot选用的是ucLibc,我以前的业务都在glibc上跑,以至于以前的程序都需要重新编译,甚至部分程序存在兼容问题。

虽说buildroot可以选择外部交叉编译器,可我的原始编译器版本arm-linux-gcc-4.4.4太老了,buildroot明确提示不建议使用,所以我不得不用原始编译器手动编译mosquitto。

作罢,想偷懒也不给机会。

非常奇怪,同样的配置文件下采用buildroot构建的交叉编译器、或本地x86编译器去编译mosquitto-2.0.14没有任何报错,用本地arm-linux-gcc-4.4.4出现若干问题。

文稿的内容讲述排查编译问题的过程,我已经将排查后的补丁放到推送链接里,补丁文件
mosquitto-2.0.14-gcc-4.4.x.patch

获取补丁途径关注程序员写个解:发送20220413

  • arm-linux-gcc-4.4.4
  • glibc-2.11.1(libc、librtpthread)
  • openssl-1.1.1(libssl、libcrypto)
  • mosquitto-2.0.14

3. 编译选项

编译mosquitto之前保证openssl、cjson等已经正确编译并安装到本地交叉编译环境,我这里安装到目录/home/${USER}/cross/imx287,如果你需要mosquitto支持更多的特性,还得预先编译更多的第三方库。

至于mosquitto支持哪些第三方库,工程目录README.md “Build Dependencies” 章节有讲解,配置方法可以直接 “make WITH_SRV=yes WITH_TLS=no” 指定,也可以编辑config.mk配置工程。 为节省时间,我采用默认配置。

在make之前要配置编译查找目录,无非是CLFAGS、LDFLAG下面是我添加到config.mk的模板。

CFLAGS+=-I/home/${USER}/cross/imx287/include/ \
		-I/home/${USER}/cross/imx287/usr/local/include/ \
		-D_GNU_SOURC

LDFLAGS+=-L/home/${USER}/cross/imx287/usr/local/lib \
		-L/home/${USER}/cross/imx287/lib \
		-lssl -lrt\
		-Wl,-rpath=/home/${USER}/cross/imx287/lib:/home/${USER}/cross/imx287/usr/local/lib

4. 重定义mosquitto_plugin_id_t

../../src/mosquitto_broker_internal.h:254: error: redefinition of typedef 'mosquitto_plugin_id_t'
/home/llg/cross/imx287/usr/local/include/mosquitto_broker.h:181: note: previous declaration of 'mosquitto_plugin_id_t' was here

配置好config.mk开始执行make编译。

提示好几个数据类型重定义错误(mosquitto_plugin_id_t、struct mqtt5__property) 低版本编译器多数据类型重定义比较严格,只要typedef后的数据类型用括号 “{}” 围住就属于定义数据类型。去掉括号则属于声明,能正常编译。

修改方法,注释掉mosquitto_broker.h文件结构体定义,用typedef重新声明它。

// mosquitto_broker_internal.h
typedef struct mosquitto_plugin_id_t{
	struct mosquitto__listener *listener;
} mosquitto_plugin_id_t;

// mosquitto_broker.h
// struct mosquitto_plugin_id_t{
// 	struct mosquitto__listener *listener;
// };
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;

同时替换mosquitto_broker.h文件里所有mosquitto_property为struct mqtt5__property。

struct mosquitto_evt_acl_check {
	void *future;
	struct mosquitto *client;
	const char *topic;
	const void *payload;
//  mosquitto_property *properties;
	struct mqtt5__property *properties;

5. prctl替换pthread_setname_np

mosquitto_client_sub.c: In function 'my_message_callback':
mosquitto_client_sub.c:18: warning: format '%s' expects type 'char *', but argument 3 has type 'void * const'
~/cross/imx287/usr/local/lib/libmosquitto.so: undefined reference to `pthread_setname_np'

mosquitto工程不仅仅生成libmosquitt.so已经生成,还包括几个配套内置应用程序,包括mosquitto代理服务器、mosquitto_pub发布者、mosquitto_sub订阅者。

在生成mosquitto代理服务器时提示pthread库未定义函数pthread_setname_np。我的交叉编译环境pthread太老pthread-2.11.so没有实现函数pthread_setname_np,x86版本pthread-2.31.0存在。

怎么解决新老版本的差异呢?

mosquitto总不会发布之初就用上pthread_setname_np函数的吧,于是我去 官网 逐个下载mosquitto历史版本,看看早期版本里,官方如何实现pthread_setname_np函数的功能。

在1.6.0版本里没有用到pthread_setname_np,查看mosquitto_loop_start如何实现的,恩~? 老版本里居然没任何替代函数,莫非它不重要吗?

// mosquitto-2.0.14
int mosquitto_loop_start(struct mosquitto *mosq)
{
	if(!mosq || mosq->threaded != mosq_ts_none) return MOSQ_ERR_INVAL;

	mosq->threaded = mosq_ts_self;
	if(!pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)){
#if defined(__linux__)
		pthread_setname_np(mosq->thread_id, "mosquitto loop");
#endif
		return MOSQ_ERR_SUCCESS;
	}else{
		return MOSQ_ERR_ERRNO;
	}
}

// mosquitto-1.6.0
int mosquitto_loop_start(struct mosquitto *mosq)
{
	mosq->threaded = mosq_ts_self;
	if(!pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)){
		return MOSQ_ERR_SUCCESS;
	}else{
		return MOSQ_ERR_ERRNO;
	}
}

遇到问题找男人 “man pthread_setname_np”

哟西,Got it。它目的是给线程命名,当某线程异常时top能根据线程名字知道哪个线程出问题,否则所有线程都继承父线程的名字。类似的用法几年前在某工程用过,再翻阅以前工程源码,那个API叫prctl。

By default, all the threads created using pthread_create() inherit the program name. The pthread_setname_np() function can be used to set a unique name for a thread, which can be useful for debugging multithreaded applications.

ptctl函数不能像pthread_setname_np那样放在父线程,否则给父线程取名了。 我把它放在线程处理函数的mosquitto__thread_main开头。

// lib/thread_mosq.c
void *mosquitto__thread_main(void *obj)
{
	struct mosquitto *mosq = obj;
	prctl(PR_SET_NAME, "mosquitto loop");  // 添加这里
    // ....
}

6、总结

解决以上2个问题后mosquitto编译成功了,后面运行测试时候还有几个小插曲:

  • 编写发布者、订阅者测试程序连接mosquitto代理服务器,只能 向环回地址127.0.0.1发起连接才能成功,向其他本地地址192.168.x.x却没有响应,即使wireshark抓包都看不到,是测试程序编写有缺陷吗?
  • 向环回地址连接成功后,却一直提示错误 “Client <unknown> disconnected due to out of memory” 是怎么回事。

两个问题我将在下一篇文章逐一排查。

我将要展示 “strace跟踪mosquitto,找到执行错误原因” 敬请期待。

相关推荐

前端入门——css 网格轨道详细介绍

上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...

Islands Architecture(孤岛架构)在携程新版首页的实践

一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...

HTML中script标签中的那些属性

HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...

CSS 中各种居中你真的玩明白了么

页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...

CSS样式更改——列表、表格和轮廓

上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...

一文吃透 CSS Flex 布局

原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...

css实现多行文本的展开收起

背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...

css 垂直居中的几种实现方式

前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...

WordPress固定链接设置

WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...

面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿

前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...

3种CSS清除浮动的方法

今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...

2025 年 CSS 终于要支持强大的自定义函数了?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...

css3属性(transform)的一个css3动画小应用

闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...

CSS基础知识(七)CSS背景

一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...

CSS 水平居中方式二

<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...

取消回复欢迎 发表评论: