新闻详情

新闻详情

首页 / 资讯中心 / 详情

ROS 2运行在普通Linux上,为什么还会出现延迟?从Linux调度器理解机器人实时性

发布时间:2026/9/29 2:05:39来源:尧图网络
ROS 2运行在普通Linux上,为什么还会出现延迟?从Linux调度器理解机器人实时性
很多人在第一次使用 ROS 2 做机器人开发时都会遇到一个看起来有些奇怪的问题程序运行起来了ROS 2 节点通信正常DDS 消息也能正常收发控制算法单次执行时间甚至只有几十微秒但是机器人运行一段时间之后控制周期还是会偶尔出现明显抖动。例如一个理论上应该每 1ms 执行一次的控制任务实际运行结果可能是0.99ms 1.01ms 1.00ms 1.03ms 0.98ms 1.02ms 8.76ms 1.01ms前面的数据看起来都没有问题偏偏偶尔出现一次 8.76ms。问题来了既然控制算法只需要几十微秒为什么一次任务还是可能等待几毫秒很多时候问题并不在 ROS 2 控制算法本身而在于控制线程什么时候能够真正获得 CPU这就涉及 Linux 内核中非常核心的一套机制——调度器Scheduler。对于普通应用来说操作系统调度器可能只是一个很底层的系统机制。但对于 ROS 2 实时控制来说调度器实际上直接决定了一个关键问题一个已经准备好执行的机器人控制线程到底什么时候能够真正开始运行理解这个问题也就理解了为什么 ROS 2 的实时性最终一定会落到 Linux 内核、CPU、线程优先级和调度策略上。一、ROS 2中的Callback为什么不是“准备好了就马上执行”上一篇文章我们讲到一个典型的 ROS 2 控制任务大致经历传感器数据到达 ↓ DDS通信 ↓ Callback Ready ↓ Executor发现Callback ↓ 线程准备执行 ↓ Linux调度器 ↓ 获得CPU ↓ Callback真正开始运行 ↓ 控制计算 ↓ 输出执行器指令这里最容易被忽略的是Callback Ready ≠ Callback Running。也就是说当一个 ROS 2 Callback 已经准备好了并不代表 CPU 此刻就一定会执行它。中间还存在一个非常重要的环节Linux SchedulerLinux 内核需要根据当前系统状态决定现在应该让哪个线程运行例如当前 CPU 上可能同时存在ROS 2控制线程 ROS 2传感器线程 视觉处理线程 网络线程 日志线程 系统服务 内核线程 硬件中断那么当控制 Callback 已经 Ready 时它需要经过线程调度才能获得 CPU。于是整个过程就变成Callback Ready ↓ 等待调度 ↓ Thread Running ↓ 开始执行这中间的时间就是实时系统非常关心的调度延迟。假设控制周期1ms Callback Ready 10.000ms Callback真正开始执行 10.004ms那么调度等待大约就是4μs如果某一次变成Callback Ready 20.000ms Callback真正开始执行 20.800ms那么调度等待就变成了800μs对于普通应用来说800μs可能完全没有感觉。但对于1kHz控制系统周期 1ms800μs已经占用了绝大部分控制周期。如果控制任务后面还需要读取数据 计算 输出那么很容易出现 Deadline Miss。因此机器人控制的实时性不仅取决于“任务执行需要多长时间”还取决于“任务什么时候能够开始执行”。这也是 Linux 调度器在 ROS 2 实时系统中的重要性。二、Linux调度器到底在做什么为什么“有CPU”不代表“马上能运行”可以把 CPU 理解成一个非常宝贵的资源。假设一个 CPU 核心当前只能同时执行一个普通线程那么系统中可能存在线程A 线程B 线程C 线程DLinux 调度器就需要不断决定现在运行谁当一个线程运行完、阻塞、被唤醒或者发生抢占时调度器可能重新进行选择。简化来看Linux Scheduler │ ┌────────────┼────────────┐ ↓ ↓ ↓ Thread A Thread B Thread C │ └──── 当前获得CPU对于普通计算机系统这套机制主要考虑系统整体的公平性、吞吐量、交互响应等。但机器人控制需要考虑的却是另外一套问题谁最重要 谁必须优先运行 谁不能长时间等待 哪些任务可以被抢占 哪些任务应该尽量不要进入实时CPU这就是实时调度和普通调度之间的重要区别。在 Linux 中不同线程可以采用不同的调度策略。对于实时应用比较常见的包括SCHED_FIFO SCHED_RR SCHED_DEADLINE而普通任务则通常使用普通调度策略。这里不需要先记住所有细节只需要理解一个核心逻辑调度策略决定了线程参与 CPU 竞争时采用什么规则。而对于机器人控制线程来说合理的调度策略往往比单纯提高 CPU 主频更加重要。三、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE实时线程到底有什么不同在 ROS 2 实时控制中经常会看到三个调度策略SCHED_FIFO SCHED_RR SCHED_DEADLINE它们解决的是不同类型的调度问题。1. SCHED_FIFO谁优先级高谁先运行SCHED_FIFO 是实时系统中非常经典的一种调度策略。可以简单理解为高优先级线程 ↓ 优先获得CPU ↓ 持续运行 ↓ 直到主动让出CPU、阻塞 或者被更高优先级实时线程抢占例如控制线程Priority 90 状态估计Priority 70 日志线程普通优先级当控制线程 Ready 后如果满足相应调度条件它可以优先于较低优先级任务获得 CPU。对于需要稳定周期执行的机器人控制任务这种模式非常有价值。但是 SCHED_FIFO 并不是“打开之后系统就自动实时”。例如控制线程 Priority 90如果这个线程内部存在长时间计算 死循环 阻塞操作 锁等待 不可控I/O那么高优先级反而可能造成新的系统问题。因此实时调度策略必须与应用设计结合起来。2. SCHED_RR实时优先级下增加时间片轮转SCHED_RR 可以理解为在实时优先级基础上增加一定的时间片轮转机制。例如同一个优先级上存在Thread APriority 80 Thread BPriority 80 Thread CPriority 80如果都处于 Ready 状态系统可以按照轮转方式让它们依次获得 CPU。因此SCHED_FIFO → 更强调同优先级任务中的先来先服务 SCHED_RR → 同优先级任务之间进行轮转它们都属于经典实时调度策略但适用场景和任务设计方式不同。3. SCHED_DEADLINE直接围绕时间约束进行调度SCHED_DEADLINE 则更加特殊。它不是简单地说我的优先级比较高而是允许任务表达更加明确的时间需求。可以粗略理解为Runtime Deadline Period例如一个周期任务每1ms运行一次系统可以围绕任务的运行预算和时间约束进行调度。这对于具有明确周期和Deadline的控制任务来说非常有吸引力。但也需要注意SCHED_DEADLINE不是“配置了就自动保证机器人控制一定实时”。真实系统中仍然存在中断 锁竞争 内存行为 驱动 I/O CPU资源 系统负载 应用执行时间等多个因素。所以实时调度策略只是完整实时系统中的一个环节。四、为什么用了实时调度ROS 2还是可能出现延迟这是非常重要的一点。如果我们把问题简单理解成“把 ROS 2 控制线程设置成高优先级就好了。”那么实际上还是低估了实时系统的复杂度。因为一个线程即使拥有较高优先级也仍然可能受到其他系统因素影响。例如第一种情况CPU资源竞争假设CPU 4 ROS 2控制线程 视觉线程 网络线程 日志线程即使控制线程优先级比较高系统仍然存在复杂的资源竞争关系。如果控制线程运行期间还需要等待其他线程提供数据那么整个控制链路依然可能被拖慢。第二种情况IRQ中断干扰CPU并不是只执行用户线程。硬件设备发生事件时CPU可能需要响应中断。例如网卡 USB PCIe 传感器 定时器 存储设备都可能产生中断。于是即使CPU 5 ↓ 专门运行ROS 2控制线程也不能简单认为这个CPU就是“绝对不会被打扰”。因此前面我们讲的CPU Affinity IRQ Affinity Core Isolation需要组合起来理解。第三种情况锁竞争假设高优先级控制线程 ↓ Mutex ↑ 低优先级数据线程如果低优先级线程持有锁而控制线程需要等待那么优先级再高也不能凭空绕过锁。这就是前一篇文章讲过的优先级反转问题。所以实时调度 实时同步机制必须一起考虑。第四种情况内存和I/O行为一个控制线程如果在实时路径中执行动态内存分配 文件操作 复杂日志 网络I/O就可能产生不可预测的阻塞或延迟。例如控制Callback ↓ printf / 日志 ↓ 文件/终端输出 ↓ 等待I/O这时候问题已经不是调度器单独能够解决的。所以实时程序通常会尽量减少实时路径上的不可预测操作。五、ROS 2 Executor与Linux Scheduler到底是什么关系这一点尤其值得讲清楚因为很多 ROS 2 初学者容易把 Executor 和 Linux Scheduler 混为一谈。实际上它们处于不同层级。可以简单理解成ROS 2层 Executor ↓ 决定 哪个Callback可以执行 Linux层 Scheduler ↓ 决定 哪个Thread获得CPU例如ROS 2 │ Executor │ ┌────────┼────────┐ ↓ ↓ ↓ Callback A B C │ ↓ Thread │ ↓ Linux Scheduler │ ↓ CPUExecutor面对的是CallbackScheduler面对的是Thread这两个机制共同决定最终执行时机。例如传感器消息到达 ↓ Callback Ready ↓ Executor选择Callback ↓ 对应线程被唤醒/运行 ↓ Scheduler决定CPU执行权 ↓ Callback真正执行所以如果某个 Callback 出现延迟不能直接得出“ROS 2 Executor有问题。”也不能直接得出“Linux调度器有问题。”真正需要分析的是整个链路。这也是为什么 ROS 2 实时优化通常不能只看某一个组件。六、一个机器人控制周期到底花在哪里假设我们有一个1kHz控制系统。理论周期T 1ms一次完整控制循环可能包含T1传感器数据产生 T2数据进入通信链路 T3Callback Ready T4Executor调度Callback T5控制线程真正获得CPU T6开始控制计算 T7控制计算完成 T8输出执行器指令那么整个响应时间可以近似理解成Total Response Time 通信延迟 Executor等待 线程调度延迟 资源等待 控制计算时间 输出延迟这时候就可以发现即使控制算法本身只需要50μs如果通信100μs Executor50μs 调度300μs 锁等待200μs 控制计算50μs 输出100μs最终就已经接近800μs而且这只是某一次执行。如果系统受到后台任务、IRQ、网络、I/O等影响调度延迟可能突然增加。于是800μs可能突然变成2ms 5ms 10ms因此机器人实时控制最重要的不是把某一个环节做到极致而是控制整个链路的最坏情况。七、为什么“CPU越强”并不等于“实时性越强”这是机器人系统设计中非常常见的误区。例如CPU A 4核心 2.0GHz CPU B 16核心 4.0GHz很多人第一反应是CPU B更强所以实时性一定更好。但实际并不一定。因为 CPU 性能解决的主要是单位时间计算能力而实时系统还需要考虑调度延迟 CPU竞争 中断 缓存 锁 内存 I/O 线程迁移 系统负载例如一台16核CPUCPU 0~15如果所有任务都毫无区分地运行视觉 AI推理 ROS 2 网络 日志 控制那么即使CPU非常强控制线程仍然可能受到各种系统行为影响。反过来一台计算能力没有那么夸张的CPU如果进行了合理的任务分区 CPU隔离 IRQ隔离 线程优先级设计 实时调度 资源管理反而可能表现出更加稳定的控制周期。所以性能决定系统能跑多快实时性决定系统能不能按时跑。这两个概念一定要分开。八、真正的ROS 2实时优化应该从“单点优化”变成“系统级优化”到了这里我们可以把前面几篇文章的内容串起来。ROS 2实时性并不是某一个参数决定的而是一条完整链路。可以把它总结成ROS 2实时系统 │ ┌─────────────┼─────────────┐ ↓ ↓ ↓ 通信 执行 调度 │ │ │ DDS/QoS Executor Scheduler │ │ │ └─────────────┼─────────────┘ ↓ Thread ↓ ┌───────┼───────┐ ↓ ↓ ↓ CPU IRQ Lock │ │ │ └───────┼───────┘ ↓ 控制算法 ↓ 硬件因此一个完整的 ROS 2 实时优化方案通常需要同时考虑第一通信。合理设计 DDS 和 QoS避免不必要的数据等待和通信开销。第二Executor。合理组织 Callback、Callback Group 和线程执行关系。第三线程。为关键控制线程设置合理的调度策略和优先级。第四CPU。通过 CPU Affinity、Core Isolation 等手段降低不同任务之间的干扰。第五中断。通过 IRQ Affinity 等机制合理安排硬件中断。第六同步。减少共享资源竞争控制 Mutex 临界区长度并考虑优先级继承等实时同步机制。第七应用。减少实时路径中的动态内存、I/O、复杂日志和不可预测操作。第八操作系统。如果系统对最坏情况延迟、确定性和资源隔离存在更高要求那么就需要从操作系统层面选择和构建更加适合实时控制的运行环境。这也是为什么在工业机器人、机械臂、人形机器人以及其他高实时性控制场景中越来越需要从ROS 2应用 实时运行环境 底层操作系统整体考虑系统架构。对于具有更高实时性、确定性和资源隔离需求的系统可以选择包括望获rtLinux在内的实时操作系统基础设施为 ROS 2 控制应用提供底层实时运行环境。这里最重要的不是简单地把某个系统贴上“实时”的标签而是要建立一条完整的技术链ROS 2 ↓ Executor ↓ 实时线程 ↓ 实时调度 ↓ CPU核心隔离 ↓ IRQ隔离 ↓ 资源隔离 ↓ 硬件控制最终目标只有一个让关键控制任务在复杂系统负载下仍然能够更加稳定、可预测地获得计算资源。九、从ROS 2到实时Linux机器人软件真正的竞争点正在发生变化早期机器人开发更加关注能不能跑起来后来开始关注算法准不准再往后则开始关注算得快不快而当机器人真正进入工业现场、复杂生产环境以及大规模部署阶段之后另外一个问题会越来越重要能不能长期稳定、确定地运行尤其是人形机器人、工业机械臂、移动机器人等系统未来可能同时运行视觉感知 语音交互 AI推理 地图构建 路径规划 运动规划 状态估计 关节控制 安全监控 网络通信这些任务的计算特征完全不同。如果所有任务都放在同一套资源中无差别运行那么系统越复杂实时控制越容易受到干扰。因此未来机器人软件架构很可能越来越强调应用层解耦 通信机制 任务调度 实时计算 资源隔离而 ROS 2 与实时Linux的关系也可以从这个角度理解ROS 2 解决机器人软件模块如何组织、通信和协作 实时Linux 解决关键任务如何更加稳定、确定地获得底层计算资源两者并不是互相替代的关系而是不同层级的技术能力。对于机器人开发者而言真正需要建立的思维也应该从“ROS 2能不能实时”逐渐转变为“我的整个机器人软件栈能不能为关键任务提供可预测的时间行为”这也是理解 ROS 2 实时控制的真正入口。当我们继续向下追问就会来到一个更加具体的问题如果已经有了实时调度策略为什么还需要SCHED_FIFO SCHED_RR SCHED_DEADLINE三种不同的实时调度方式它们分别适合什么样的机器人任务1kHz关节控制、100Hz状态估计、30Hz视觉任务又应该如何设计优先级和调度策略下一篇我们就从机器人实际任务出发详细拆解《SCHED_FIFO、SCHED_RR、SCHED_DEADLINE有什么区别机器人实时控制到底该怎么选》从Linux调度策略真正进入机器人实时任务设计。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

DeepSeek Harness 桌面端全攻略:从安装配置到插件加载失败排查 2026/9/29 4:48:44

DeepSeek Harness 桌面端全攻略:从安装配置到插件加载失败排查

DeepSeek 官方把 Harness 桌面端安装包挂到 GitHub Releases 页面的时候,没有发公告,官网首页也看不到入口,我也是日常刷 Release 记录时无意翻到的。装上之后用了两天,这货确实比网页版体验好太多——对话、写代码、挂 Skill、调…

阅读更多 →
内存泄漏自动检测系统实战:从MFC CString到SolidWorks插件 2026/9/29 4:48:44

内存泄漏自动检测系统实战:从MFC CString到SolidWorks插件

这两年我排查过最磨人的一类Bug,不是功能报错,也不是闪退,而是那种"跑着一两天没事,第三天后半夜悄悄把服务器堆满"的内存泄漏。更难受的是,这类问题没法靠断点调试,得靠人去代码里一行行盯。但人…

阅读更多 →
2026 AI服务器电源主控DSP国产替代选型与实操指南 2026/9/29 4:48:37

2026 AI服务器电源主控DSP国产替代选型与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AD24工程化避坑:库导入、差分走线、DRC与Gerber输出 2026/9/29 4:48:37

AD24工程化避坑:库导入、差分走线、DRC与Gerber输出

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Java图书管理系统源码解析:从部署到改造的完整指南 2026/9/29 4:48:37

Java图书管理系统源码解析:从部署到改造的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
TaoToken 场景下的 telnet 文件传输:下载与上传的配置骨架与验证 2026/9/29 4:48:37

TaoToken 场景下的 telnet 文件传输:下载与上传的配置骨架与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉