当前位置: 首页 > article >正文

【4】为什么Go能挂住成千上万个goroutine,线程却没爆?一次讲透GMP调度模型

如果你写 Go 写的久了很容易对一件事习以为常请求来了起一个goroutine后台任务想并发跑再起几个goroutine网络连接一多程序里挂着成千上万个goroutine好像也不算什么稀奇事。代码写起来很顺读起来也像普通的阻塞程序。可只要停下来追问一句就会发现这件事并没有看上去那么理所当然。如果这些执行路径都在并发往前推进为什么线程数没有跟着一起膨胀如果线程总会碰到阻塞系统调用、网络等待和 CPU 争抢程序为什么又没有轻易被拖垮再往前追一步如果某个goroutine一直不肯让出 CPU或者某个线程正卡在系统调用里调度器到底靠什么把其他工作继续推下去很多介绍Go并发的材料到了这里会先给一个很快的答案goroutine是轻量线程。这个说法不能算错但只说到了表面。真正难的部分不在“它比线程轻”这件事上而在它为什么能轻这种轻量在阻塞、调度和并行度控制面前为什么还站得住Go运行时要解决的不是简单地把线程包装得更便宜一点而是让大量待执行的工作在有限的线程和有限的并行度上稳定流动。真正撑起这套并发模型的是G、M、P三层分工围绕它们建立起来的队列、让渡、窃取和恢复机制把这几层关系摆正后面再看GOMAXPROCS、netpoll、抢占调度和runtime/proc.go就不会觉得它们像一堆零散技巧。先抓住四个最容易卡人的问题G、M、P三个角色分别是什么为什么偏偏要拆成这三层。线程真的阻塞时为什么整个调度系统没有被一起拖住。调度器平时是按什么顺序找任务的为什么它不靠一个全局大队列解决一切。网络 I/O 明明写得像阻塞代码为什么底层又不需要一连接一线程地死等。把这四层关系先看稳**GMP的主骨架就差不多立住了。**后面的抢占、公平性和版本细节都只是沿着这副骨架继续展开。真正要看清的不是goroutine比线程“轻”多少而是Go运行时到底怎样让大量工作在有限资源上稳定流动。先把G、M、P的角色摆正为什么只把goroutine叫轻量线程还不够把goroutine只理解成轻量线程往往还是不够。真正需要补上的是这种“轻”靠什么维持。Go调度器没有把并发执行这件事直接压到线程身上而是拆成了三层G负责承载待执行的工作M负责把代码真正放到操作系统线程上运行P负责提供执行Go用户代码时所必需的调度上下文也正因为多了P这一层运行时才有办法一边限制同一时刻的并行度一边处理大量goroutine与少量线程之间的映射关系。图里把本地队列、全局队列和工作窃取一起画出来就是为了先把这套分工的骨架立住。图示先看清G、M、P的分工以及本地队列、全局队列和工作窃取如何连在一起。关键不是一对一映射而是三层分工关键不在“一个goroutine配一条线程”而在怎样让大量G在有限的M和P上有序流动。G是工作M是执行者P是执行资格和调度上下文。先把这三层拆开后面再看阻塞、窃取、抢占这些动态过程时就不容易把它们误解成某种“线程池技巧”。G负责工作M负责执行P负责让执行这件事真正成立。角色分工先立住之后下一个问题就是这套结构一旦遇到现实里的阻塞会不会立刻失灵。线程既然是真的线程总会碰到系统调用而只要线程会卡住调度器就必须回答谁继续往前跑。阻塞发生时为什么系统还能继续往前跑系统调用阻塞是理解GMP时最容易卡住的一步。直觉上看只要某条执行路径进入阻塞调用承载它的线程就停住了而线程一旦停住整个并发系统似乎也会跟着受影响。Go调度器真正解决的恰恰是**“线程会阻塞”带来的连锁问题**。关键做法不是让线程永远不阻塞而是当某个M因系统调用暂时卡住时把它手里的P及时让出去让别的线程接手继续执行其他 runnableG。这样阻塞就被限制在局部不会扩散成整片调度停摆。图示某个M因阻塞系统调用停住后P如何让出并由其他线程接手继续推进剩余的 runnableG。这里要抓住的重点不是“系统调用不贵”也不是“线程不会卡住”而是阻塞发生时调度器仍然可以把执行能力保留下来。可以把这件事压缩成两个判断真正被卡住的是那条进入系统调用的执行链不是整个Go程序的并发推进能力P的关键就在这里它把“线程是否阻塞”和“系统还能不能继续调度别的工作”拆成了两件事。被阻塞的是某条执行链不是整个调度系统。不过只知道阻塞时可以让出P还不够。调度器能继续往前跑前提是它知道下一步该去哪里找活。光理解“阻塞时怎么救场”还只是半截接下来还得补上“平时到底怎么调度”。调度器平时是按什么顺序找任务的理解GMP不能只停留在静态分工还得往前追一步当某个线程已经拿到P准备继续执行下一段Go代码时它到底先从哪里找任务。这里没有一个“全局平均分配器”在背后统一发号施令调度器走的是一条层次很明确的优先路径先看runnext再看当前P的本地队列本地没有再去碰全局队列还不够再考虑从别的P那里工作窃取最后再看netpoll有没有已经就绪、可以恢复执行的网络 I/O 任务这个顺序直接决定了调度开销、局部性和全局竞争的强弱。图示调度器为当前P寻找下一个G时的优先路径从runnext到本地队列再到全局队列、窃取和netpoll。这一步的结论可以压缩成一句话调度器优先在本地解决问题只在本地耗尽时才逐层向外找补。这样做不是为了绝对公平而是为了在下面几件事之间保持平衡吞吐响应调度成本Go调度器并不是一个一视同仁的大池子而是一套“本地优先、全局兜底、必要时再平衡”的分层机制。调度器不是平均发活而是优先本地解决缺活时再逐层向外找补。走到这里调度器的日常工作方式已经大致清楚了平时先在本地找任务必要时再向外扩展线程阻塞了也可以通过让渡P把系统继续推下去。剩下最值得单独拎出来的一类场景就是网络 I/O。它在业务代码里看起来最像老老实实堵在那里等结果但运行时内部的处理方式又和直觉差得最远。网络 I/O 为什么能写得像阻塞代码网络 I/O 是另一个很容易被表象带偏的地方。业务代码写起来像顺序阻塞调用读写接口如果数据没来就在那里等等到了再继续往下走。可如果底层真的是“一条连接占住一条线程”地等待Go就很难在高并发网络场景里维持现在这种资源利用方式。运行时真正做的是把下面两件事拆开代码写起来像阻塞底层调度不能被长期占住某个G发起网络读写后如果文件描述符暂时还没就绪运行时会先把这个G挂起把等待事件交给netpoll同时把线程和P释放回调度器继续处理别的 runnableG。等事件真正到来再把对应的G放回队列等待重新调度。图示网络 I/O 尚未就绪时等待中的G先挂起事件到来后再由netpoll唤醒并放回调度队列。真正要抓住的是网络 I/O 的“阻塞感”主要发生在G这一层而不是把整个线程长期绑死在一次等待上。对业务代码来说执行流依然是顺序的对运行时来说这其实是一条挂起等待事件重新入队恢复执行的调度链。正因为有这条链路Go才能同时保留直观的编程模型和较高的并发承载能力。对业务代码来说像阻塞对运行时来说是挂起、等待、唤醒和重新调度。把前面四张图连起来看GMP并不是四个互不相干的小技巧拼在一起而是一套围绕“怎样让大量工作稳定流动”展开的整体设计。G、M、P先把角色拆开P的让渡解决阻塞扩散本地队列和工作窃取控制日常调度netpoll再把网络等待这类高频场景接回主线。走到这里调度器的主骨架已经基本立住了。接下来还需要补上的是另外两件事如果某个goroutine一直占着 CPU 不放运行时怎么把它抢下来而GOMAXPROCS又究竟在限制什么。忙循环为什么最终还是会被抢占抢占要解决的是没有停顿点时怎么办把前面的阻塞、队列和网络等待都看清之后最后一个很自然的问题变成了纯计算场景。假设有一个goroutine什么都不等不做系统调用不碰网络 I/O也不主动调用Gosched()只是一直埋头跑计算。按最粗糙的直觉看只要它一直不让别的任务是不是就只能一直等着如果真是这样前面讲的那些机制就只对“愿意停下来”的任务有效调度器的公平性会非常脆弱。只要有一个忙循环足够长其他 runnablegoroutine就会被压在后面垃圾回收和调度延迟也会一起变差。Go运行时不能把公平性建立在“业务代码最好自觉一点”这件事上所以它必须再补一层能力某个goroutine长时间占着 CPU 不放时运行时要能主动把它拉下来。这就是抢占要解决的问题。它针对的不是“阻塞了怎么办”而是**“根本没有阻塞也没有自愿让出时怎么办”。**前面几节讲的是调度器如何利用停顿点继续往前推这一节讲的则是当停顿点迟迟不出现时运行时如何自己制造一个。早期的Go调度更接近协作式思路运行中的goroutine往往要在函数调用、通道操作、系统调用这类位置自然交回执行权。只要代码路径里有这些点问题并不大可一旦遇到长时间运行的纯计算循环这种做法就会变得被动。后来运行时把抢占能力补强了核心思路也不复杂调度器不会无限期等某个goroutine自己让出 CPU而是会在它占用 CPU 过久时想办法把“该停一下了”这件事递到它当前的执行路径上。抢占不是从任意位置硬切走这里最容易混淆的地方是把抢占理解成“立刻从任何指令位置硬切走”。实际并不是这个意思。运行时仍然要考虑安全边界尤其要避免在不合适的位置把栈、寄存器和执行状态切乱。更贴近事实的说法是某个goroutine运行得太久时运行时会给它打上“应该被抢占”的标记并尽快把执行流引到合适的安全点让调度器重新接管对业务代码来说外部观感是“忙循环最终还是会被切下来”对运行时来说这件事仍然是在可控边界内完成的。把这层机制放回前面的主线里看调度器其实一直在做两件互补的事。只要某个goroutine因阻塞、等待或主动交回执行权而停下来就立刻利用这个空档安排别的工作如果某个goroutine长时间不停那就不能一直等它主动停下来而要由运行时自己推动一次切换。前者解决“有空档时怎么利用”后者解决“迟迟没有空档时怎么办”。看到这里GMP的日常运转逻辑已经比较完整了。再往下就该收束到另一个经常被说错的点了。很多人一提GOMAXPROCS第一反应就是“线程数上限”或者“最多开多少个并发任务”。这两个说法都不准确。真正决定同时能跑多少段Go代码的不是G的数量M的总数而是P的数量。GOMAXPROCS限制的不是goroutine数也不是线程总数它先不是任务总数和线程总数GOMAXPROCS这个名字很容易把人带偏。它看上去像某种“最大线程数”设置再加上平时又常和 CPU 核心数一起出现于是很多人顺手就把它理解成“线程池大小”或者“最多能开多少个并发任务”。可如果把前面的GMP关系图重新拿回来对照这个解释很快就会露出问题。先看最直接的一层GOMAXPROCS并不限制goroutine的数量。程序里完全可以同时存在几十万、几百万个goroutine其中绝大多数都只是处在等待、可运行或者未来某个时刻才会继续推进的状态。Go运行时并不会因为GOMAXPROCS8就只允许存在 8 个goroutine这两件事根本不在一个维度上。可以这样对照理解goroutine的数量对应的是系统里一共有多少份待处理工作GOMAXPROCS管的是同一时刻最多允许多少份Go用户代码并行执行再看第二层GOMAXPROCS也不等于线程总数上限。线程是M这一层的资源而M会因为系统调用阻塞、网络轮询、运行时后台任务等原因出现增减。某个时刻程序里实际存在的线程数可能比GOMAXPROCS大也可能远小于它。只要这些线程里有一部分正在阻塞运行时就可能需要额外的M去接手剩余的P把调度继续往前推。所以拿“线程总数”去理解GOMAXPROCS很容易把系统调用阻塞这类关键场景直接抹平。它真正限制的是可用并行度真正更准确的说法是GOMAXPROCS限制的是可用并行度。也就是同一时刻最多有多少个P可以让普通Go代码并行执行。因为每个P都像一张“执行许可证”M拿到P之后才能真正跑用户态Go代码所以P的数量才是那条决定并行度的硬边界。程序里可以有很多G在排队也可以有额外的M因阻塞和唤醒在系统里流动但真正同时向前推进的Go代码段数最终还是被P的数量卡住。GOMAXPROCS限制的不是任务总数也不是线程总数而是同一时刻能并行执行多少段Go代码。这样再回头看一个很常见的场景很多误解就能自动消掉。假设机器有 8 个逻辑 CPU而GOMAXPROCS也设成 8。即使程序里有一千个 runnablegoroutine同一时刻也只会有 8 份Go代码真正并行执行剩下的都要等待调度反过来即使系统里因为阻塞系统调用存在超过 8 条线程这也不代表有超过 8 段用户态Go代码在一起跑。线程可以多等待中的工作也可以更多但并行执行普通Go代码的“闸门”仍然在P这里。这也是为什么官方后来更明确地把GOMAXPROCS解释成 available parallelism。这个说法比“最大线程数”准确得多因为它直接点出了运行时真正要控制的对象不是线程总量不是任务总量而是并行推进用户态Go代码的能力上限。只要把这个口径放稳很多表面上绕来绕去的现象都会顺下来。goroutine可以很多因为待处理工作可以很多线程可以比GOMAXPROCS更多因为阻塞和后台任务会让运行时需要额外的M但真正同时跑起来的那一层始终要经过P。抢占和GOMAXPROCS要放在一起看把抢占和GOMAXPROCS放在一起看会发现它们补的是同一件事的两面GOMAXPROCS给并行度画出边界保证同一时刻最多能跑多少抢占保证在这条边界之内不会因为某个忙循环长期霸占执行权让别的任务永远挤不进来一个负责把入口收住一个负责让入口内部保持流动。正因为这两层同时存在Go调度器才不是“谁抢到线程谁一直跑”的粗放模型而是一套既限制并行度、又维持公平推进的运行时机制。再回头看开头那个最直观的现象答案其实已经很清楚了。程序里可以挂着成千上万个goroutine却不需要把线程数一起撑大不是因为运行时偷偷做了什么难以名状的优化而是因为它从一开始就没有把下面三件事混成一层工作线程并行执行资格G、M、P把角色拆开队列和窃取让工作流动起来P的让渡把阻塞控制在局部netpoll把等待中的网络 I/O 接回调度主线抢占和GOMAXPROCS则把公平性和并行度边界一起收住。走到这里GMP就不再只是三个缩写而是一套能解释日常Go并发行为的具体运行机制。Go的并发之所以能“看起来简单、跑起来不乱”靠的不是口号式的轻量线程而是G、M、P和整套调度机制一起工作。

相关文章:

【4】为什么Go能挂住成千上万个goroutine,线程却没爆?一次讲透GMP调度模型

如果你写 Go 写的久了,很容易对一件事习以为常:请求来了,起一个 goroutine;后台任务想并发跑,再起几个 goroutine;网络连接一多,程序里挂着成千上万个 goroutine,好像也不算什么稀奇…...

动态时间规整(DTW):跨越时间维度的相似性度量

一、DTW解决了什么? 在处理时间序列数据时,我们最常碰到的难题就是“不同步”。比如: 语音识别:同样是说“你好”,有人语速快,有人语速慢,直接拿时间来对齐比对是完全不准的。股票走势&#xff…...

PromptX:基于MCP协议的AI智能体上下文平台部署与实战指南

1. 项目概述:PromptX,一个重新定义AI交互方式的智能体上下文平台 如果你和我一样,每天都在和Claude、Cursor这类AI工具打交道,那你一定遇到过这样的困境:想让AI帮你写一份专业的产品需求文档,你得先花半小…...

Revornix:基于LLM的AI代码助手架构解析与实战指南

1. 项目概述:一个面向开发者的AI代码助手最近在GitHub上闲逛,发现了一个挺有意思的项目,叫“Revornix”。乍一看这个名字,可能有点摸不着头脑,但点进去之后,发现这其实是一个基于大型语言模型(L…...

在线抠图换背景免费工具怎么选?网页端哪个准、微信小程序有哪些方案(2026 年)

很多人做图片抠图换背景,默认打开电脑搜在线网页工具,但实际上微信小程序这条路线在 2026 年已经够用,而且省掉了下载、注册、传图再导回来的琐碎步骤。下面会重点拆解一款叫抠图喵的微信小程序,放在第一个讲——它在你问的“在线…...

09华夏之光永存:盘古大模型开源登顶世界顶级——开源生态共建指南(第九篇)

09华夏之光永存:盘古大模型开源登顶世界顶级——开源生态共建指南(第九篇) 标签:#华为盘古 #开源生态 #大模型社区 #昇腾生态 #鸿蒙AI生态 #国产AI共建 免责声明 本文为盘古大模型10篇系列开源连载第九篇,严格承接前8篇…...

UI----4

UI----4 一、分栏控制器(UITabBarController) 1. 作用 管理多个平级界面,底部显示标签栏,点击切换不同页面(类似微信底部:首页、通讯录、我)。 2. 核心特点 是容器控制器,不自己显示…...

【2026年最新600套毕设项目分享】微信小程序软件缺陷管理系统(30176)

有需要的同学,源代码和配套文档领取,加文章最下方的名片哦 一、项目演示 项目演示视频 项目演示视频2 二、资料介绍 完整源代码(前后端源代码SQL脚本)配套文档(LWPPT开题报告/任务书)远程调试控屏包运…...

玩转 Python:多线程、装饰器、视觉检测与正则匹配实战

Python 作为一门简洁又强大的编程语言,在多线程编程、函数增强、计算机视觉、文本处理等多个领域都有着广泛的应用。本文将结合几个实用的代码案例,带你上手 Python 的多线程、装饰器、OpenCV 颜色检测和正则表达式匹配,从基础应用到实际场景…...

基于Python与LLM API构建轻量级命令行问答工具

1. 项目概述:一个轻量级命令行问答工具最近在折腾一些自动化脚本,经常需要在终端里快速查询一些信息,比如某个命令的用法、一个概念的简单解释,或者把一段代码从Python翻译成Go。每次都打开浏览器、切换标签页、输入关键词&#x…...

ARM RealView Debugger多项目管理与调试实战

1. ARM RealView Debugger多项目管理实战解析在嵌入式开发领域,高效管理多个关联项目是提升开发效率的关键。ARM RealView Debugger(以下简称RVD)通过容器项目(Container Project)机制,为开发者提供了强大的…...

AudioMoth Dev开发板:全频谱声学监测与生物声学研究利器

1. AudioMoth Dev开发板深度解析AudioMoth Dev是一款基于Silicon Labs EFM32 Wonder Gecko MCU的全频谱声学开发板,专为野外声学监测和生物声学研究设计。作为AudioMoth设备的开发版本,它保留了核心音频采集功能的同时,提供了更丰富的硬件接口…...

HarmonyOS APP开发之玩透 postCardAction 的三大通信心法

玩透 postCardAction 的三大通信心法做鸿蒙 UI 开发的兄弟,只要碰过服务卡片(Service Widget),多半都经历过这样一种“血压飙升”的时刻:产品经理想要在卡片上做一个简单的按钮交互,你顺手写了个点击事件&a…...

科学AI智能体的强化学习训练与应用实践

1. 科学智能体训练概述科研工作往往充斥着大量重复性劳动——文献查阅、实验流程管理、多模态数据处理等机械性工作占据了研究者大量时间。科学AI智能体的出现,正在改变这一现状。这类智能体能够承担文献综述、假设生成、实验规划、计算任务提交、实验室操作协调、结…...

ComfyUI Impact Pack完整安装指南:3步解决节点缺失问题

ComfyUI Impact Pack完整安装指南:3步解决节点缺失问题 【免费下载链接】ComfyUI-Impact-Pack Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more. 项目地址: https:/…...

农业数据主权危机:MCP 2026要求实时上传作业轨迹、油耗、工况等137个字段——你的ISOBUS网关真的合规吗?

更多请点击: https://intelliparadigm.com 第一章:农业数据主权危机的本质与MCP 2026立法动因 农业数据主权危机并非技术失灵的表象,而是全球粮食价值链中权力结构失衡的深层投射。当跨国农企平台通过IoT传感器、卫星遥感和农机API持续采集田…...

沙箱隔离失效的11个隐性信号,第8个已在金融客户生产环境触发RCE——MCP 2026隔离健康度自检清单

更多请点击: https://intelliparadigm.com 第一章:MCP 2026沙箱隔离失效的底层机理与威胁图谱 MCP 2026 是一种面向多租户云原生环境的轻量级容器化策略执行框架,其沙箱设计依赖于 Linux cgroups v2、user namespace 嵌套及 seccomp-bpf 策略…...

【U-Net 数据集制作】如何制作自己的图像分割数据集?(标注与格式转换),图像分割数据集制作与转换神器

前言 在前面的课程中,我们像搭积木一样手写了 U-Net 的网络架构。很多同学迫不及待地想把自己的图片喂进网络开始“炼丹”。但是,深度学习界有一句名言:“数据决定了模型的上限,而网络结构只是在逼近这个上限。” 在实际项目中,做数据准备往往比写网络更让人崩溃: 用标…...

贝叶斯网络原理与应用实战指南

1. 贝叶斯信念网络入门指南第一次接触贝叶斯网络时,我被那些复杂的箭头和条件概率表搞得晕头转向。直到有一次在医疗诊断项目中,我才真正理解这种概率图模型的强大之处——它能够直观地表达变量间的依赖关系,处理不确定性问题。本文将带您从零…...

Diffusers库实现AI图像修复与扩展的实战指南

1. 使用Diffusers库进行图像修复与扩展的完整指南在数字图像处理领域,图像修复(Inpainting)和图像扩展(Outpainting)是两项极具实用价值的技术。作为一名长期使用Stable Diffusion的开发者,我发现Hugging Face的Diffusers库为这些任务提供了强大的工具链…...

基于多智能体与RAG的DeepResearchAgent:AI驱动的自动化文献综述实践

1. 项目概述:一个能帮你“读论文”的智能研究助手最近在折腾AI Agent领域,发现了一个挺有意思的开源项目——SkyworkAI的DeepResearchAgent。简单来说,这玩意儿就是一个能帮你做深度文献调研的智能体。想象一下,你拿到一个全新的研…...

豆包AI与DeepSeek的区别

豆包AI和DeepSeek都是当前流行的中文大型语言模型(LLM)助手,但它们由不同公司开发,在背景、功能、性能和适用场景上存在差异。1. 开发者背景与起源豆包AI:由字节跳动公司(抖音、今日头条的母公司&#xff0…...

HTML头部元信息避坑指南技术文章大纲

HTML头部元信息避坑指南技术文章大纲核心元标签的常见错误与正确用法<meta charset>未声明或声明位置错误导致乱码 <title>过长或重复影响SEO与用户体验 <meta name"viewport">缺失导致移动端适配问题 <meta http-equiv>误用引发兼容性问题S…...

离婚案件数据分析系统设计:基于玉溪案例的抚养权判决预测模型

一、技术背景与问题定义作为一名在玉溪从事法律科技工作的从业者&#xff0c;我这些年一直在思考一个问题&#xff1a;抚养权判决的结果能不能被预测&#xff1f;说实话&#xff0c;传统上大家觉得这是不可能的——毕竟法官要综合考量那么多因素&#xff1a;孩子的意愿、父母双…...

数据科学实战:OSEMN框架详解与案例分析

1. 数据科学家如何系统化解决问题&#xff1a;OSEMN框架详解 作为一名从业多年的数据科学顾问&#xff0c;我经常被问到"数据科学家到底如何思考问题"。事实上&#xff0c;这个领域最宝贵的不是掌握多少算法&#xff0c;而是系统化解决问题的框架思维。今天我要分享的…...

信息熵:从概念到机器学习应用的全面解析

1. 信息熵的概念起源与核心定义信息熵这个概念最早由克劳德香农在1948年的论文《通信的数学理论》中提出&#xff0c;当时是为了解决通信系统中的信息量化问题。但有趣的是&#xff0c;这个概念其实脱胎于物理学中的热力学熵。香农在思考如何度量信息时&#xff0c;向著名数学家…...

Arduino与VL53L0X激光测距传感器开发指南

1. 项目概述&#xff1a;基于Arduino的ToF激光测距传感器应用开发激光测距技术在现代智能设备中扮演着越来越重要的角色。作为该技术的代表产品&#xff0c;ST VL53L0X ToF传感器凭借其毫米级精度、2米测距范围和940nm不可见激光等特性&#xff0c;被广泛应用于机器人避障、工业…...

stm32f103zet6使用STM32CubeMx移植原子fsmc(有讲解)

本次使用原子stm32f103zet64.3寸mcu屏&#xff0c;学了原子的例程发现虽然是hal库开发但是并没有使用stm32cubemx开发而是纯库函数&#xff0c;我之前的工程都是基于cubemx所以我想进行适配&#xff0c;现在把移植过程罗列如下&#xff0c;有问题可以评论区问我&#xff0c;stm…...

网络故障定位工具怎么搭配:Wireshark、tcpdump、监控平台各自该在什么时候上场?

网络故障定位工具怎么搭配&#xff1a;Wireshark、tcpdump、监控平台各自该在什么时候上场&#xff1f; 很多团队的网络排障效率低&#xff0c;不是因为没人干活&#xff0c;而是因为工具顺序用反了&#xff1a;明明问题还在“先确认范围”的阶段&#xff0c;就急着抓全量包&am…...

10华夏之光永存:盘古大模型开源登顶世界顶级——全系列终章总结与未来使命(第十篇)

10华夏之光永存&#xff1a;盘古大模型开源登顶世界顶级——全系列终章总结与未来使命&#xff08;第十篇&#xff09; 标签&#xff1a;#华为盘古 #终章总结 #国产AI自立自强 #华夏本源AI #世界顶级大模型开源全闭环 免责声明 本文为盘古大模型十篇系列开源连载最终篇、第十篇…...