lwIP:宏 LWIP_TCPIP_CORE_LOCKING(内核锁定)

news2024/11/10 18:28:34

从 lwIP-2.0.0 开始,在 opt.h 中多了一个宏开关 LWIP_TCPIP_CORE_LOCKING,默认使能。这个宏是启用内核锁定功能的。
本文探索这个宏的前世今生。


2007 年 5 月 24 日,Simon Goldschmid (以下简称 西蒙 )提交了一个任务:task #6935(使用当前 socket/netconn API 需要解决的问题)。

西蒙提出,当前的 socket/netconn API 还存在某些设计问题需要改进,比如:

1.将消息机制改为互斥(锁定 netconns)

move from message passing to mutual exclusion (lock netconns)

这里需要解释一下 消息机制 是什么。

在使用操作系统的情况下,lwIP 内核作为操作系统的一个任务tchip_thread )运行,内核线程应用程序线程 间的通讯是通过消息机制来完成的。

在当时,距离发布 lwIP-1.3.0 版本还有 10 个月,在这个版本中,如果 应用程序线程 使用 sendto 函数发送 UDP 数据,这是一个复杂的过程。实际上应用程序线程无权发送数据,它会先构造一个称为 TCPIP_MSG_API 的消息,连带发送的数据信息,投递给 内核线程,由内核线程进行实际的数据发送:

请添加图片描述

从图中可以看出,一个普通的数据发送,需要两个线程协同、进行两次任务切换才能完成。多年以来,lwIP 对外声称都是”为了获得良好的性能,你应该使用 raw API“。这就是原因!因为线程间通讯低效造成的。

为什么要让内核线程完成实际的发送?直接在 应用程序线程 中发送不可以吗?

不可以!

这涉及到多年以来 lwIP 对外声称的另一个注意事项:“lwIP 不是线程安全的”!!!

从 lwip 诞生以来,直到最近发布的 lwIP-2.1.x,以及可以看到的将来,lwIP 都不是线程安全的

所以 lwIP 采用了一个迂回的策略,用来满足多线程编程:使用 并发设计 中的 队列模式

举一个很好理解的例子。

如果有两个任务使用同一个 串口 打印调试信息,任务 A 打印:

printf("Task A: ABCDEFG\n");

任务 B 打印:

printf("Task B: 1234567\n");

任务A正在打印的时候,可能被任务B打断,这时任务A的打印信息就会显得不完整,任务 A 打印的信息被任务 B 打印的信息分成两部分:

Task A: ABTask B: 1234567
CDEFG

出现这个问题的原因是有多个任务同时使用一个资源,那么让任务不去同时访问资源,更进一步,干脆让任务不访问资源不就解决了吗。队列模式 就是这个思路,即所有任务都不直接使用串口资源,而是将要打印的信息放到一个队列中,串口发送也独立出一个任务,该任务从队列中取出信息,打印信息。完美解决大家争资源的问题。

lwIP 处理 线程不安全 也是用的这个思路:创建一个邮箱队列,投递消息相当于入队,内核线程 从邮箱队列中取出消息,根据消息的指示做出相应的动作,所有 应用程序线程 都不访问 lwIP 内核,也就避免了线程不安全的问题。

除了一个问题外,效率低。

西蒙萌生出了改变这一现状的想法:

  • 对于发送,我们可以锁定整个核心,而不是将消息传递给另一个线程。这样 TX 可以优先处理。锁定互斥锁的运行时间不应比消息传递长多少。
  • 对于接收,同样可以锁定整个核心,这样 tchip_thread 只需要处理 RX定时器

随着讨论的进行,大家觉得使用全局互斥锁是个可行的方案。

Frédéric Bernon (以下简称 佛雷德里克)根据这个思路修改了代码,并进行了测试。他的测试代码是用 sendto 函数发送 1458 字节的数据(UDP 连接),测试结果如下:

Sequential API: lwip_sendto()raw API: udp_sendto
使用消息机制204 us74 us
使用全局互斥量67 us74 us

可以看出,使用全局互斥量后:

  • lwip_sendto 函数用时减少了 3 倍
  • 与 udp_sendto 函数执行时间相比,仅慢了 3us 。

可以说效果拔群。 佛雷德里克 是怎么做到的呢?原因在于他使用了全局互斥量让发送数据成了 原子操作 ,从而避免了线程间的切换,实现了在 应用程序线程 中调用 udp_sendto 函数直接完成数据的发送:

请添加图片描述

由于少了消息传递和任务切换的开销,速度自然也就快了起来。

这种使用互斥量保护共享资源的操作,使用了 并发设计 中的 守卫调用模式。如果多个线程以某种方式同时调用相互干扰的服务集合,可以使用守卫调用模式使得多个线程串行访问服务。最常见的实现方式是使用互斥量给共享资源加锁。

继续用上面的例子,有两个任务使用同一个 串口 打印调试信息,则可能出现打印乱套的问题。如果换一种方式,任务 A 在使用串口前,先把串口锁定,一旦锁定,除非任务 A 主动解锁,否则其它任务都不能使用串口。这样就能避免任务 A 正在使用串口打印信息时,被任务 B 打断的现象了。

2007 年 6 月 9 日, 佛雷德里克 将这个更改推送到了 lwIP 代码仓库,这是历史上第一次,宏 LWIP_TCPIP_CORE_LOCKING 出现在 lwIP 的源码中,默认设置为 0 ,即不启用该新功能。

但此时的代码还是实验性质的,仅供 lwIP 开发者测试用,在这个宏开关的注释中,有着明显的提示:

/* EXPERIMENTAL, Don't use it if you're not an active lwIP project member */

实验性质,如果你不是 lwIP 项目的开发人员,请不要使用它

之后,使用互斥量 锁定内核 的操作方式不断完善:

  • 2007 年 7 月底,API 消息(TCPIP_MSG_API)已经几乎完全可以使用锁定内核的方式替换掉,这包括连接、发送等操作
  • 2010 年 2 月份,西蒙 第一次引入宏 LWIP_TCPIP_CORE_LOCKING_INPUT,底层数据包输入消息(TCPIP_MSG_INPKT)也可以选择使用锁定内核的方式了。当然,这依旧是实验性质的。
  • 2016 年 3 月 17,终于, LWIP_TCPIP_CORE_LOCKINGLWIP_TCPIP_CORE_LOCKING_INPUT 不再是实验性质的,它们正式向用户开放了!从第一次讨论“将消息机制改为互斥”,到最终推出这个功能,用了将近 10 年!
  • 2016 年 7 月 1,宏 LWIP_TCPIP_CORE_LOCKING 的默认值修改为 1 ,这意味着解决 “lwIP 不是线程安全的”的方案, lwIP 开发者更推荐使用互斥锁。
  • 2016 年 11 月 10, lwIP-2.0.0 发布,在这个版本中,我们第一次可以放心使用互斥锁方案。

时代变了。“为了获得良好的性能,你应该使用 raw API” 这一印象,从 lwIP-2.0.0 开始,要改写了!从此,使用 Sequentialsocket API 也可以达到接近 raw API 的性能!

有关操作系统移植层的信息,可以参考我的这篇博文。






读后有收获,资助博主养娃 - 千金难买知识,但可以买好多奶粉 (〃‘▽’〃)
千金难买知识,但可以买好多奶粉


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/548132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DriveAct:用于自动驾驶汽车细粒度驾驶员行为识别的多模态数据集

Drive&Act:A Multi-modal Dataset for Fine-grained Driver Behavior Recognition in Autonomous Vehicles 摘要1. 简介2. 其它驾驶员动作数据集3. Drive&Act数据集3.1 数据采集3.2 记录的数据流传感器设置和视频流3D Body Pose3D Head PoseInterior ModelA…

接口优化技巧汇总

1.批处理 批量思想:批量操作数据库,这个很好理解,我们在循环插入场景的接口中,可以在批处理执行完成后一次性插入或更新数据库,避免多次IO。 //批量入库 batchInsert();2.异步处理 异步思想:针对耗时比较…

短视频去水印接口 支持各短视频平台去水印 快速稳定

短视频去水印接口 支持各短视频平台去水印,抖音、快手、微视、西瓜等。 快速稳定 不限次 免费测试 接口开发文档 返回格式: JSON 请求方式: GET/POST 请求示例: 请求参数说明: 字段必填类型说明url是String短视…

听说你想成为一名6的飞起的黑客,这些资料怎么能少

重点提醒:本项目工具来源于互联网,是否含带木马及后门请自行甄别!!Hvv来即,请大家提高警惕!!! 受限于篇幅原因,无法全部展示,如果你需要的话,可以…

【正点原子STM32连载】 第十章 STM32CubeMX简介 摘自【正点原子】STM32F103 战舰开发指南V1.2

1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十章…

教你精通Java语法之第十四章、枚举

目录 一、背景及定义 二、使用 2.1switch语句 2.2常用方法 三、枚举优点缺点 四、枚举和反射 4.1枚举是否可以通过反射,拿到实例对象呢? 五、总结 六、面试问题 一、背景及定义 枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织…

触发器章节小结

触发器(Flip Flop) 4.1 SR锁存器(Set-Reset Latch) 4.1.1 或非门构成的SR锁存器 SD称为置位端或置1输入端; RD称为复位端或置0输入端。 当SD 1、RD 0时,Q1、Q’0。在SD 1信号消失以后(即SD 回到0)&#…

AI绘画-Midjourney基础1-突破想象的界限:掌握文本引导的图像生成技巧

Midjourney是一款 AI 绘画工具,可以根据你的提示(本文中称为 prompt)创作出各种图像。你只需要在Discord上和一个机器人聊天,就可以用简单的命令来控制它。目前已不支持免费试用,可以选择付费计划来获得更多功能和优势…

viet构建项目及<script setup>的用法

vite构建项目 官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite vite 官网:https://vitejs.cn 什么是 vite?—— 新一代前端构建工具。 优势如下: 开发环境中,无需打包操作,可快速的冷启动。…

操作系统易错题

操作系统易错题 假设某硬盘由5个盘片构成(共有8个记录面),盘面有效记录区域的外直径为30cm,内直径为10cm,记录位密度为250位/mm,磁道密度为16道/mm,每磁道分16个扇区,每扇区512字节&…

【图像分割】卫星遥感影像道路分割:D-LinkNet算法解读

前言 因为毕设中的部分内容涉及到卫星遥感影像道路分割,因此去对相关算法做了一些调研。 本文所使用数据集为DeepGlobe,来自于CVPR2018年的一个挑战赛:DeepGlobe Road Extraction Challenge。 D-LinkNet为该挑战赛的冠军算法。 考虑到D-Lin…

时间序列预测 | Matlab基于遗传算法优化BP神经网络(GA-BP)的时间序列预测,matlab代码

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab基于遗传算法优化BP神经网络(GA-BP)的时间序列预测,matlab代码 评价指标包括:R2、MAE、MSE、RMSE等,代码质量极高,方便学习和替换数据。 部分源码 %% 清空环境变量 warning off …

Flink学习——处理函数ProcessFunction及多流转换

处理函数 在DataStream的更底层,我们可以不定义任何具体的算子(如map(),filter()等)二只提炼出一个统一的“处理”(process)操作 。它是所有转换算子的概括性的表达。可以自定义处理逻辑。 所以这一层接口就…

Springcloud1--->Eureka注册中心

目录 Eureka原理Eureka入门案例编写EurekaServer将user-service注册到Eureka消费者从Eureka获取服务 Eureka详解基础架构高可用的Eureka Server失效剔除和自我保护 Eureka原理 Eureka:就是服务注册中心(可以是一个集群),对外暴露自…

开心档之MySQL 数据类型

目录 MySQL 数据类型 数值类型 日期和时间类型 字符串类型 MySQL 中定义数据字段的类型对你数据库的优化是非常重要的。 MySQL 支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。 数值类型 MySQL 支持所有标准 SQL 数值数据类型…

矢量图形处理控件CAD .NET介绍以及安装

CAD .NET一款在CAD领域被广泛应用的控件,可以快速准确的阅读DWG和DXF文件,并且通过Windows GDI方法绘制件,支持多种文件格式,包括DWG、DXF、Gerber、光栅图像等,并支持部分编辑功能。 CAD.NET最新下载https://www.evg…

Android 性能优化篇之SharedPreferences使用优化

简介: SharedPreferences(以下简称SP)是Android本地存储的一种方式,是以key-value的形式存储在/data/data/项目包名/shared_prefs/sp_name.xml里 SP的使用及存在的问题 SharedPreferences(以下简称SP)是Android本地存储的一种方式,是以key-…

机器学习吴恩达笔记第一篇——基于梯度下降的线性回归(零基础)

机器学习吴恩达笔记第一篇——基于梯度下降的线性回归(零基础) 一、线性回归——理论(单变量) 1、 假设函数h(x)为: ​ h ( x ) θ 0 θ 1 X h(x)\theta_0\theta_1 X h(x)θ0​θ1​X 2、要拟合数据成一条直线&…

如何让 300 万程序员爱上 CODING?

**《DNSPod十问》**是由腾讯云企业中心推出的一档深度谈话栏目,通过每期向嘉宾提出十个问题,带着广大读者站在产业互联网、科技领域精英的肩膀上,俯瞰各大行业发展趋势和前沿技术革新。 刘毅,腾讯云 CODING CEO、腾讯云开发者产品…

第十六章_Redis案例落地实战bitmap/hyperloglog/GEO

统计的类型有哪些 亿级系统中常见的四种统计 聚合统计 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计 复习命令 交并差集和聚合函数的应用 排序统计 抖音短视频最新评论留言的场景,请你设计一个展现列表。考察你的数据结构和设计思…