菜鸟科技网

taskset命令如何绑定进程到特定CPU核心?

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

taskset命令如何绑定进程到特定CPU核心?-图1
(图片来源网络,侵删)

什么是 CPU 亲和性?

CPU 亲和性 是一种操作系统调度器的特性,它试图将某个进程“绑定”到一个或一组特定的 CPU 核心(或逻辑核心)上。

  • 为什么需要它?
    1. 提高缓存命中率:当进程频繁地在同一个 CPU 核心上运行时,该 CPU 的 L1/L2/L3 缓存可以更有效地保存和重用该进程的数据,减少了缓存未命中和跨核心数据传输的开销,从而提升性能。
    2. 避免 CPU 频繁切换:在多核系统中,如果进程在不同的 CPU 核心间来回迁移(称为 "migration"),会带来额外的开销,绑定可以减少这种迁移。
    3. 资源隔离:在虚拟化或容器化环境中,可以确保某个关键服务(如数据库)的进程不会被其他无关进程挤占 CPU 资源,保证其性能稳定。
    4. 特定硬件需求:某些 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。

taskset命令如何绑定进程到特定CPU核心?-图2
(图片来源网络,侵删)
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,然后转换成十六进制。

示例

  • 你想在核心 02 上运行:位位置 0 和 2 为 1。
    • 二进制:0101 -> 十六进制:0x5
  • 你想在核心 1, 2, 3 上运行:位位置 1, 2, 3 为 1。
    • 二进制:1110 -> 十六进制:0xE

对于超过 4 个核心的系统,taskset 会自动处理,8 核心的掩码范围是 0x10xFF


常用选项

  • -p, --pid: 操作一个已存在的进程,而不是启动一个新进程,必须配合 pid 使用。
  • -c, --cpu-list: 使用 CPU 核心列表(如 0,2-3)来代替十六进制掩码,这种方式更直观,尤其是在核心数量较多时。
  • -v, --verbose: 显示更详细的信息。

实用示例

示例 1:启动一个新进程并绑定到特定 CPU 核心

假设你的系统有 8 个核心(0-7),你想让 dd 命令(一个 I/O 密集型命令)只在核心 5 上运行。

taskset命令如何绑定进程到特定CPU核心?-图3
(图片来源网络,侵删)
# 使用十六进制掩码
# 核心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 亲和性

  1. 找到你想操作的进程 ID

    sleep 1000 &
    [1] 12345  # 假设 sleep 的 PID 是 12345
  2. 查看当前进程的 CPU 亲和性

    # 使用 -p 选项和 pid
    taskset -p 12345
    # 输出可能类似于:
    # pid 12345's current affinity mask: f
    # f (二进制 1111) 表示可以在所有核心上运行
  3. 修改进程的 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 的输出结果是一致的。


重要注意事项

  1. 需要 root 权限:修改其他用户的进程或系统关键进程的亲和性通常需要 sudo 权限。
  2. 性能影响是双向的
    • 正面:绑定到合适的 CPU 可以提升性能。
    • 负面:如果绑定不当,可能会导致 CPU 资源不均衡,如果你把所有高负载的进程都绑定到核心 0,而其他核心空闲,整体系统性能反而会下降。
  3. 不是万能药:CPU 亲和性只是一个优化工具,它不能解决所有性能问题,在应用它之前,应该先用性能分析工具(如 perf, vmstat)找到瓶颈。
  4. cpuset cgroup 的区别
    • taskset 是一个一次性命令,它直接修改进程的亲和性掩码,如果进程重新启动,设置会丢失。
    • cpuset 是 cgroup 的一个子系统,可以创建更持久、更精细的 CPU 和内存节点隔离组,它更适合用于容器化(如 Docker, Kubernetes)和需要长期资源隔离的场景。taskset 更适合于临时的、命令行的性能调试和优化。

taskset 是一个非常强大且简单的 Linux 命令行工具,用于快速、临时地控制进程的 CPU 亲和性,它是系统管理员和开发者进行性能调优、资源隔离和问题排查的利器,掌握它,尤其是在多核服务器环境下,非常有价值。

分享:
扫描分享到社交APP
上一篇
下一篇