目标:把指定 CPU 核从系统调度里隔离出来,只给你的实时机器人 / ROS2 程序专用,不被系统后台、其他进程抢占,实现微秒级低延迟。
一、核心原理
- 内核启动参数
isolcpus:开机就把指定 CPU 核隔离,普通进程不会自动跑上去 - 再用
pthread_setaffinity_np把你的 ROS2 线程绑到隔离核 - 隔离核只跑你的业务线程,系统后台完全不占用
二、第一步:修改 GRUB 内核参数 隔离 CPU 核
1. 编辑 grub 配置
bash
运行
sudo gedit /etc/default/grub
找到这一行:
plaintext
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
改成(举例:隔离 第 6、7 核)
plaintext
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=6,7"
说明:
- CPU 核从 0 开始编号
- 你之前代码绑核 7,这里就隔离 6,7 两个核给实时任务用
2. 更新 grub 并重启
bash
运行
sudo update-grub
sudo reboot
3. 验证是否隔离成功
重启后执行:
bash
运行
cat /proc/cmdline
能看到 isolcpus=6,7 就代表隔离生效 ✅
三、第二步:把 ROS2 程序线程绑定到隔离核
你之前代码里的 bindThreadToCpu() 就是干这个的,我给你优化成工业级标准版,直接可用:
cpp
运行
#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
// 绑定当前线程到指定CPU核(必须是已隔离的核)
bool bindThreadToCpu(int cpu_id)
{
int total_cpu = sysconf(_SC_NPROCESSORS_ONLN);
if (cpu_id < 0 || cpu_id >= total_cpu)
{
std::cerr << "CPU核非法,范围 0~" << total_cpu - 1 << std::endl;
return false;
}
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_id, &cpuset);
int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (ret != 0)
{
std::cerr << "绑定CPU失败, err:" << ret << std::endl;
return false;
}
std::cout << "线程已绑定到隔离CPU核: " << cpu_id << std::endl;
return true;
}
在节点构造里调用:
cpp
运行
// 绑到已经隔离的核7
bindThreadToCpu(7);
四、第三步:抬高实时优先级(配合隔离更稳)
只隔离不够,还要提高线程调度优先级,加函数:
cpp
运行
#include <sys/resource.h>
// 设置线程实时优先级
bool setThreadRealTimePriority(int prio = 90)
{
struct sched_param param;
param.sched_priority = prio;
// SCHED_FIFO 实时调度
if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0)
{
std::cerr << "设置实时优先级失败,需sudo运行" << std::endl;
return false;
}
return true;
}
使用顺序:
cpp
运行
bindThreadToCpu(7);
setThreadRealTimePriority(90);
运行时必须加 sudo 才能生效实时优先级:
bash
运行
sudo ./你的节点 或 sudo ros2 run xxx xxx
五、第四步:验证绑定 & 隔离是否生效
1. 查看进程绑核
先看你的节点 PID:
bash
运行
ps aux | grep 你的节点名
看该进程运行在哪个核:
bash
运行
taskset -pc 进程PID
输出只显示 6,7 就是绑到隔离核了。
2. 看系统进程不跑在隔离核
bash
运行
htop
按 F6 可以看每个进程所在 CPU,隔离核几乎没有系统进程,只有你的程序。
六、推荐最佳配置(直接照抄)
4 核 / 6 核 / 8 核通用方案:
- GRUB 参数:
plaintext
isolcpus=4,5,6,7
- 业务线程统一绑:6、7
- 开
SCHED_FIFO实时优先级 - 配合 PREEMPT_RT 实时内核(延迟更低)
七、常见问题
- 绑了核还是有抖动
- 没开 RT 内核 / 没设
SCHED_FIFO优先级
- 没开 RT 内核 / 没设
- 改了 grub 不生效
- 没执行
sudo update-grub+ 没重启
- 没执行
- 普通用户不能设高优先级
- 加 sudo 运行,或配置
/etc/security/limits.conf永久授权
- 加 sudo 运行,或配置