taskset 是一个在 Linux 系统中用于查看和设置进程 CPU 亲和性 的命令,它允许你指定一个进程只能在哪些 CPU 核心上运行,或者不能在哪些 CPU 核心上运行。

什么是 CPU 亲和性?
CPU 亲和性 是一种操作系统调度器的特性,它试图将某个进程“绑定”到一个或一组特定的 CPU 核心(或逻辑核心)上。
- 为什么需要它?
- 提高缓存命中率:当进程频繁地在同一个 CPU 核心上运行时,该 CPU 的 L1/L2/L3 缓存可以更有效地保存和重用该进程的数据,减少了缓存未命中和跨核心数据传输的开销,从而提升性能。
- 避免 CPU 频繁切换:在多核系统中,如果进程在不同的 CPU 核心间来回迁移(称为 "migration"),会带来额外的开销,绑定可以减少这种迁移。
- 资源隔离:在虚拟化或容器化环境中,可以确保某个关键服务(如数据库)的进程不会被其他无关进程挤占 CPU 资源,保证其性能稳定。
- 特定硬件需求:某些 NUMA (Non-Uniform Memory Access) 架构的服务器,为了获得最佳性能,需要将进程绑定到特定内存节点对应的 CPU 核心。
taskset 命令的基本语法
taskset 命令有两种主要用法:
启动新进程并设置其 CPU 亲和性
taskset [选项] CPU_MASK 命令 [参数...]
CPU_MASK: 一个十六进制或二进制掩码,表示进程可以运行的 CPU 核心。命令: 你想要启动的任何命令或脚本。参数...: 命令的参数。
修改已存在进程的 CPU 亲和性
taskset [选项] CPU_MASK pid
CPU_MASK: 同上,新的 CPU 亲和性掩码。pid: 你要修改的进程 ID。
CPU 掩码 的表示方法
这是 taskset 命令的核心,CPU 掩码用一个位图来表示哪些 CPU 核心是可用的。
假设你的系统有 4 个 CPU 核心,编号为 0, 1, 2, 3。

| CPU 核心 | 位位置 | 十六进制掩码 | 二进制掩码 | 含义 |
|---|---|---|---|---|
| 无 | - | 0x0 |
0000 |
不在任何核心上运行 |
| 0 | 0 | 0x1 |
0001 |
仅在核心 0 上运行 |
| 1 | 1 | 0x2 |
0010 |
仅在核心 1 上运行 |
| 2 | 2 | 0x4 |
0100 |
仅在核心 2 上运行 |
| 3 | 3 | 0x8 |
1000 |
仅在核心 3 上运行 |
| 0 和 1 | 0, 1 | 0x3 |
0011 |
在核心 0 和 1 上运行 |
| 1 和 3 | 1, 3 | 0xA |
1010 |
在核心 1 和 3 上运行 |
| 全部 | 0, 1, 2, 3 | 0xF |
1111 |
在所有核心上运行(默认) |
计算方法:将你希望启用的 CPU 核心对应的位设置为 1,然后转换成十六进制。
示例:
- 你想在核心 0 和 2 上运行:位位置 0 和 2 为 1。
- 二进制:
0101-> 十六进制:0x5
- 二进制:
- 你想在核心 1, 2, 3 上运行:位位置 1, 2, 3 为 1。
- 二进制:
1110-> 十六进制:0xE
- 二进制:
对于超过 4 个核心的系统,taskset 会自动处理,8 核心的掩码范围是 0x1 到 0xFF。
常用选项
-p, --pid: 操作一个已存在的进程,而不是启动一个新进程,必须配合pid使用。-c, --cpu-list: 使用 CPU 核心列表(如0,2-3)来代替十六进制掩码,这种方式更直观,尤其是在核心数量较多时。-v, --verbose: 显示更详细的信息。
实用示例
示例 1:启动一个新进程并绑定到特定 CPU 核心
假设你的系统有 8 个核心(0-7),你想让 dd 命令(一个 I/O 密集型命令)只在核心 5 上运行。

# 使用十六进制掩码 # 核心5对应位位置5,2^5 = 32,十六进制为0x20 taskset 0x20 dd if=/dev/zero of=/tmp/testfile bs=1M count=1000 # 使用 --cpu-list 选项,更直观 taskset --cpu-list 5 dd if=/dev/zero of=/tmp/testfile bs=1M count=1000
示例 2:启动一个新进程并绑定到多个 CPU 核心
想让一个编译任务在核心 2, 3, 4, 5 上运行。
# 使用十六进制掩码 # 核心2,3,4,5对应位位置2,3,4,5 # 二进制: 111100 -> 十六进制: 0x3C taskset 0x3c make -j4 # 使用 --cpu-list 选项 taskset --cpu-list 2-5 make -j4
示例 3:查看和修改已存在进程的 CPU 亲和性
-
找到你想操作的进程 ID:
sleep 1000 & [1] 12345 # 假设 sleep 的 PID 是 12345
-
查看当前进程的 CPU 亲和性:
# 使用 -p 选项和 pid taskset -p 12345 # 输出可能类似于: # pid 12345's current affinity mask: f # f (二进制 1111) 表示可以在所有核心上运行
-
修改进程的 CPU 亲和性: 假设你想把上面的
sleep进程限制在核心 0 和 1 上运行。# 使用十六进制掩码 0x3 taskset -p 0x3 12345 # 再次查看确认 taskset -p 12345 # 输出应该变为: # pid 12345's current affinity mask: 3
示例 4:结合 ps 命令查看进程的亲和性
你可以通过 /proc 文件系统查看任何进程的亲和性。
# 查看 PID 为 12345 的进程的亲和性 cat /proc/12345/status | grep Cpus_allowed # 输出类似于: # Cpus_allowed: 00000003 # Cpus_allowed_list: 0-1
这和 taskset -p 的输出结果是一致的。
重要注意事项
- 需要 root 权限:修改其他用户的进程或系统关键进程的亲和性通常需要
sudo权限。 - 性能影响是双向的:
- 正面:绑定到合适的 CPU 可以提升性能。
- 负面:如果绑定不当,可能会导致 CPU 资源不均衡,如果你把所有高负载的进程都绑定到核心 0,而其他核心空闲,整体系统性能反而会下降。
- 不是万能药:CPU 亲和性只是一个优化工具,它不能解决所有性能问题,在应用它之前,应该先用性能分析工具(如
perf,vmstat)找到瓶颈。 - 与
cpusetcgroup 的区别:taskset是一个一次性命令,它直接修改进程的亲和性掩码,如果进程重新启动,设置会丢失。cpuset是 cgroup 的一个子系统,可以创建更持久、更精细的 CPU 和内存节点隔离组,它更适合用于容器化(如 Docker, Kubernetes)和需要长期资源隔离的场景。taskset更适合于临时的、命令行的性能调试和优化。
taskset 是一个非常强大且简单的 Linux 命令行工具,用于快速、临时地控制进程的 CPU 亲和性,它是系统管理员和开发者进行性能调优、资源隔离和问题排查的利器,掌握它,尤其是在多核服务器环境下,非常有价值。
