登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux taskset 怎样把进程固定到指定 CPU 核心

来源:17golang原创

时间:2026-11-08 04:07:02 369浏览 收藏

Linux taskset 怎样把进程固定到指定 CPU 核心

排查某个服务是否被调度到指定 CPU 时,taskset 最直接:新启动命令使用 taskset -c CPU列表 命令,已有进程使用 taskset -pc CPU列表 PID,再用 taskset -pc PID 读取当前亲和性。这里的“固定”是限制进程可运行的 CPU 集合,不等于强制它立刻迁移到某一颗核心。

官方地址:https://man7.org/linux/man-pages/man1/taskset.1.html

如果目标是把 PID 1234 限制在 CPU 3,执行 sudo taskset -pc 3 1234;如果是启动新命令,则执行 taskset -c 3 ./worker。设置后仍要读取亲和性确认,权限和 CPU 编号不合法都会导致失败。

先把“启动命令”和“已有 PID”分开

taskset 的命令行有两种入口。默认模式把给定掩码或 CPU 列表应用到新命令;带 -p 时操作对象变成已有 PID。把这两种写法混用,是最常见的排查起点。

目标写法关键含义
启动新命令taskset -c 3 ./worker命令从 CPU 3 的亲和性集合开始
修改已有进程taskset -pc 3 1234把 PID 1234 的亲和性集合改成 CPU 3
读取已有进程taskset -pc 1234读取 PID 1234 的 CPU 列表
处理全部线程taskset -apc 3 1234把 PID 对应任务的线程一起处理

CPU 列表比十六进制掩码更适合人工排查

CPU 亲和性本质上是一个位掩码,最低位对应逻辑 CPU 0。人工写命令时可以用 -c 或 --cpu-list 把目标核心写成列表,单核、多核和范围都更直观。

# 单个 CPU:只允许进程使用逻辑 CPU 3
taskset -c 3 ./worker

# 多个离散 CPU:允许使用 CPU 1、4、5
taskset --cpu-list 1,4,5 ./worker

# 连续范围:允许使用 CPU 0 到 CPU 3
taskset -c 0-3 ./worker

# 步长范围:允许使用 CPU 0、2、4、6
taskset -c 0-6:2 ./worker

对已有进程设置 CPU 列表时,-p 和 -c 要组合使用,即 taskset -pc 0-3 1234。官方手册特别区分了两种场景:--cpu-list 的无 -p 形式用于启动新命令,已有 PID 则用合并后的 -pc。

taskset、CPU 列表、亲和性掩码和进程之间的静态关系说明图
图1:结构说明图,展示 taskset、CPU 列表、十六进制掩码与进程可运行 CPU 集合的关系;这是静态说明图,不是运行截图。

启动新命令时直接绑定 CPU 集合

新任务还没有 PID 时,直接把 CPU 列表放在命令前面。taskset 设置的是调度器看到的 CPU 亲和性,后面的参数原样传给目标命令。

# 让 worker 只在 CPU 2 和 CPU 3 上运行
# --cpu-list 让列表含义清楚,后面的参数属于 worker
taskset --cpu-list 2,3 ./worker --queue image

# 用十六进制掩码表达同一个集合:二进制低位的第 2、3 位为 1
# 0xC 对应逻辑 CPU 2 和 CPU 3
taskset 0xC ./worker --queue image

列表写法适合人工维护,掩码写法适合已有配置或脚本。不要只看命令是否返回成功;如果程序自身创建了多个线程,后续还要确认线程范围是否符合预期。

已有进程用 -p 修改,线程场景加 -a

服务已经运行时,先拿到 PID,再用 -p 修改。下面示例把 PID 1234 限制到 CPU 3,并用第二条命令读取结果。

# 修改已有进程的 CPU 亲和性
sudo taskset -pc 3 1234

# 读取当前 CPU 列表,确认设置对象仍是这个 PID
taskset -pc 1234

如果进程包含多个工作线程,-a 表示把给定 PID 对应的全部任务(线程)一起读取或设置:

# 把 PID 1234 的全部线程限制在 CPU 3 和 CPU 4
# -a 处理该 PID 关联的全部任务,-p 表示不重新启动命令
sudo taskset -apc 3,4 1234

# 读取全部线程的亲和性,观察是否存在单独的线程设置
taskset -apc 1234

这里的 PID 是操作入口,不应把线程范围理解为一个抽象的“进程总开关”。多线程程序如果只修改了主线程,其他线程仍可能保留自己的亲和性,因此排查时要明确是否需要 -a。

设置成功不等于进程已经跑在目标核心

taskset 返回成功,主要说明底层亲和性设置被接受,含义是线程不会在新集合之外运行;这不保证它已经立即迁移到某个目标 CPU,也不保证会一直停在单个 CPU 上。多个 CPU 都在集合中时,调度器仍可以在集合内部选择。

可以把结果分成三层理解:

  1. 集合是否正确:用 taskset -pc PID 读取当前列表。
  2. 目标 CPU 是否合法:集合至少要包含当前系统存在的 CPU,空集合会被拒绝。
  3. 线程是否覆盖:多线程服务需要决定只改主任务还是用 -a 一起处理。
已有 PID、线程集合、权限和读取结果之间的静态关系说明图
图2:关系说明图,展示已有 PID 到线程任务、权限检查和读取结果的对应边界;这是静态说明图,不是运行截图。

报错时按 CPU、权限和对象三条线排查

CPU 编号或掩码没有对应的有效核心

如果掩码对应不到当前系统的有效 CPU,taskset 会报错。先读取一个已知 PID 的当前列表,再根据这个列表选择目标,不要把另一台机器上的 CPU 编号直接照搬。

修改别人的进程缺少权限

普通用户可以修改属于自己的进程;修改其他用户的进程通常需要 CAP_SYS_NICE,实际运维命令常见形式是使用有权限的账号执行 sudo taskset ...。读取进程亲和性通常不要求同样的修改权限。

内核每 CPU 线程不是普通用户进程

部分内核每 CPU 线程不能按普通用户进程的方式设置。即使某次设置返回了成功,也不要把它解释成线程已经迁移;应以任务本身的调度语义和读取结果为准。

一组可直接套用的速查命令

# 查看已有 PID 的当前 CPU 列表
taskset -pc 1234

# 将已有 PID 限制到 CPU 0 到 CPU 3
# -p 操作已有 PID,-c 把参数解释为 CPU 列表
sudo taskset -pc 0-3 1234

# 启动新命令并限制 CPU 集合
# -- 后面的参数属于目标程序,不属于 taskset
taskset -c 0-3 -- ./worker --mode batch

# 多线程进程全部任务一起设置
# 需要修改其他用户的进程时,按实际权限使用 sudo
sudo taskset -apc 0-3 1234

如果只记一条规则:新命令用 taskset -c 列表 命令,已有 PID 用 taskset -pc 列表 PID,多线程再考虑 -a,最后用读取命令确认。

相关问题

taskset 的 CPU 编号从 1 开始吗?

不是。位掩码的最低位对应逻辑 CPU 0,CPU 列表也按系统显示的逻辑编号书写。不要把“第一颗核心”写成 CPU 1;先以目标机器的 CPU 编号为准。

为什么 taskset 设置成功但 ps 看到的 CPU 没变?

设置成功表达的是可运行集合已经改变,不是立即迁移保证。进程可能仍在集合中的原 CPU 上运行,也可能稍后才被调度到另一个允许的 CPU。

已有 PID 能直接写 taskset -c 3 1234 吗?

不能把它当作修改已有 PID 的通用写法。已有进程应使用 -p,CPU 列表形式写成 taskset -pc 3 1234;无 -p 时,最后的参数会被当作要启动的命令。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>