taskset 命令速查表 - CPU 亲和性绑核命令大全
taskset 解决的是「要不要让这个进程只用哪些核」,典型触发场景有三类:延迟毛刺但 CPU 利用率并不高(往往是跨 NUMA 节点访存或线程被调度到不同物理核上)、跑基准测试想减少迁移抖动、以及多租户机器上把自家进程隔离到空闲核避免被邻居抢占。它的实现只是改写任务的 CPU 亲和性掩码,所以从 jobs -l 或 /proc/<pid>/status 的 Cpus_allowed_list 可以随时核对是否真的绑住了。注意绑核并不必然变快:核数给少了并行度下降反而更慢,多线程进程只绑主线程更是白做,因此表里把 CPU 列表格式、十六进制掩码、绑定运行中进程、查看亲和性、NUMA 相关命令与 isolcpus 内核参数并列,方便对照选更合适的手段。
典型使用场景
面向做性能隔离、把「谁在抢我的核」变成可验证事实的工程师。taskset 是最轻的 CPU 隔离手段:不改内核、不建 cgroup、对运行中的 PID 立刻生效且随时可回退,适合在共享机器上给实时任务、数据库或某个 CPU 密集型进程圈定几个逻辑核。必须先建立的认知是它的边界:taskset 绑的是**逻辑 CPU 集合**,不是 NUMA 节点(那要 numactl),也不改变内核调度策略;而且在容器里它只能看到 cgroup 已经分配给你的 CPU,改了也绑不出去。
基础用法 6
taskset -p <pid>taskset -c -p <pid>taskset -c 0,1 <command>taskset -c 0-3 <command>taskset -p <mask> <pid>taskset -cp 0,1 <pid>CPU 掩码与列表格式 7
0x000000010x000000030x0000000f-c 0-c 0,2,4-c 0-3,8-11taskset -c 0xff <command>绑定运行中进程 4
taskset -cp 0 $(pgrep nginx)for p in $(pgrep -f app); do taskset -cp 0-3 $p; donetaskset -cp 0-3 <pid>taskset -ap 0-1 <pid>查看亲和性与系统信息 5
cat /proc/<pid>/status | grep Cpus_allowedcat /sys/devices/system/cpu/onlinenproclscpulscpu | grep NUMANUMA 架构优化 5
numactl --hardwarenumactl -c 0 -m 0 ./appnumactl --cpunodebind=0 --membind=0 ./appnumastat -p <pid>numactl --interleave=all ./app实用场景 5
taskset -c 0-3 ./cpu_intensive_apptaskset -c 4-7 ./realtime_apptaskset -c 0 nginxtaskset -c 1,2 mysqlisolcpus=2,3相关工具 5
htoptop -1mpstat -P ALL 1pidstat -t -p <pid> 1cset shield -c 4-7参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
-c <list> | 以 CPU 列表格式指定亲和性,最易读,支持 0,1、0-3、0-3,8-11 混写 | taskset -c 0-3 <command> |
-p <mask> <pid> | 查看或修改运行中进程的亲和性,不重启即可生效 | taskset -cp 0,1 <pid> |
0x0000000f | 十六进制掩码写法,等价于 CPU 0-3;taskset 默认按掩码解析 | taskset -c 0xff <command> |
-a | 作用于指定 PID 的所有线程而非仅主线程,多线程服务必须加 | taskset -ap 0-1 <pid> |
Cpus_allowed_list | /proc/<pid>/status 中的可观测字段,验证绑定是否真的生效 | cat /proc/<pid>/status | grep Cpus_allowed |
易错点与避坑指南
现象taskset -cp 0,1 <pid> 报 Invalid argument,或者容器里绑定一个超出范围的 CPU 直接失败。
原因容器里能看到的是宿主 CPU 编号集合,但实际可用集合受 cgroup 限制;超出授权范围的任务会被内核拒绝。
处置先 cat /sys/devices/system/cpu/online 和 cat /proc/<pid>/status | grep Cpus_allowed 看真实可用集合再绑。
现象给多线程进程绑定后,htop 里仍有线程跑在别的核上。
原因不带 -a 时只作用于主线程(线程组 leader),其余线程各自为政。
处置改用 taskset -ap 0-1 <pid>,一次覆盖所有线程。
现象把进程绑到某些核后延迟反而变高,跨核访问内存频繁。
原因taskset 只绑 CPU,不绑内存位置;进程在 node 1 的核上跑却在读 node 0 的内存。
处置改用 numactl -c 0 -m 0 ./app 同时绑 CPU 与内存,或用 numactl --cpunodebind=0 --membind=0 ./app。
现象taskset -c 0-3 <command> 直接报错,提示亲和性里至少要有一个 CPU 在线。
原因指定范围里包含了离线 CPU,或本机在线编号并非从 0 连续排布。
处置用 nproc / cat /sys/devices/system/cpu/online 拿到真实在线编号后重新取值。
排障路径
1确认绑定是否真的生效
cat /proc/<pid>/status | grep Cpus_allowedCpus_allowed 是掩码、Cpus_allowed_list 是列表形式,两者必须与 taskset -p 的输出一致。
2批量给一个服务所有进程改亲和性
for p in $(pgrep -f app); do taskset -cp 0-3 $p; donepgrep -f 按命令行匹配;漏掉 -a 时改的是主线程,需要 taskset -ap 0-3 $p。
3先摸清机器的 CPU 与 NUMA 拓扑
nproc && lscpu | grep NUMA && numactl --hardware隔离前必须知道有哪些在线 CPU、有几个 NUMA 节点,否则掩码取了非法值。
4绑定后逐核观察是否真的分开了
mpstat -P ALL 1需 sysstat;每核使用率分摊到预期的核上才算成功,pidstat -t -p <pid> 1 可看线程级分布。
命令示例
把 CPU 密集型应用限制在 CPU 0-3
taskset -c 0-3 ./cpu_intensive_app这样应用永远不会调度到 0-3 之外的核,等于把它与其它负载物理隔开。
把 MySQL 固定在离散的两个核上
taskset -c 1,2 mysql离散列表与 0-3 这类范围写法可以混用,混合时写成 0-3,8-11 即可。
批量把匹配到的进程都绑到 CPU 0-3
for p in $(pgrep -f app); do taskset -cp 0-3 $p; done主进程派生出多个子进程时逐个改绑;脚本里 pgrep -f 匹配的是完整命令行,注意别把无关进程一起匹配进来。
核对某个进程真实生效的 CPU 掩码
cat /proc/12345/status | grep Cpus_allowed输出里的 Cpus_allowed_list 是内核视角的权威结果,比你敲过的命令更能说明问题。
常见坑与注意事项
- 改绑前先 taskset -p pid 记录原掩码,回滚时按原值改回,否则出问题无法还原到操作前的状态。
- 多线程服务必须加 -a,只绑主线程会让其余线程继续在所有核之间游走,等于没做隔离。
- 容器里 taskset 只能绑 cgroup 已经分配给你的 CPU,指定范围外的编号会直接报 Invalid argument。
- 亲和性集合里至少要有一个在线 CPU,全部指定为离线 CPU 时 taskset 会拒绝执行。
- 绑得太紧反而可能更慢,跨核访问内存的开销会抵消收益;NUMA 架构下需要 CPU 与内存同节点请改用 numactl。
提示
- CPU 亲和性可以减少缓存失效,提升性能,但过度绑定可能导致负载不均。
- 实时应用(如高频交易、音视频处理)适合绑定到隔离核心。
- NUMA 架构下,CPU 和内存节点绑定能显著减少跨节点访问延迟。
- taskset -c 使用 CPU 列表格式比十六进制掩码更易读,推荐日常使用。
- isolcpus 内核参数在启动时隔离 CPU,比 taskset 更彻底但需重启生效。
- 多线程进程需要用 -a 参数同时设置所有线程,否则只影响主线程。
- taskset -pc 0-3 <PID> 改绑前先 taskset -pc <PID> 记录原 mask,回滚时按原值改回即可。
- taskset -a 用于多线程进程,把所有线程一起绑;不加 -a 只改主线程,/proc/<PID>/task 下每个线程需单独处理。
- lscpu -e=CPU,NODE 查看 CPU 与 NUMA 节点对应关系,绑核时让 CPU 号与目标内存节点就近可显著降延迟。
常见问题
taskset 绑的是 CPU 核还是 NUMA 节点?
绑的是逻辑 CPU 集合,一颗物理核在超线程下会算作两个逻辑 CPU,taskset 操作的粒度是后者。要按 NUMA 节点把 CPU 和内存一起绑到同一节点上,那不是 taskset 的活,要用 numactl --cpunodebind=0 --membind=0 这类命令,先用 numactl --hardware 看清节点分布。
taskset -c 0,1 command 和 taskset -cp 0,1 pid 有什么区别?
前者是启动时绑定:这个命令一启动就只能待在 CPU 0 和 1 上,进程退出后绑定随之消失。后者是改运行中的进程:传入已有 PID,把它的亲和性改成 CPU 0 和 1,不需要重启、立刻生效,进程照常运行。改之前建议先 taskset -p pid 记下原值以便回滚。
我给一个多线程服务绑了核,htop 里为什么还有线程跑在别的 CPU 上?
因为不加 -a 时只改了主线程的亲和性,其他线程各自保留原来的掩码。要把进程及其所有线程一起绑,写 taskset -ap 0-1 pid,-a 的作用就是把设置应用到该 PID 的每一个线程上。想确认每个线程的实际掩码,去 /proc/<pid>/status 里看 Cpus_allowed。
十六进制掩码 0x0000000f 到底对应哪几个 CPU?
从低位开始数,第 0 到第 3 位是 1,对应 CPU 0、1、2、3,也就是列表写法里的 0-3。同理 0x00000001 只是 CPU 0,0x00000003 是 CPU 0 和 1,0xff 则覆盖 CPU 0-7。因为掩码要自己数位,日常排查和配置更推荐 -c 列表格式。
改完亲和性怎么确认它真的生效了?
用 cat /proc/<pid>/status 配合 grep Cpus_allowed,输出里的 Cpus_allowed_list 就是当前实际允许的 CPU 集合,和你设置的列表一致才算生效。想做横向观察,htop 看每核使用率、mpstat -P ALL 1 看各核实时负载,绑定后各核负载是否真的分开了,是最直接的效果判据。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。