3. taskset 命令入门:查看与设置 CPU 亲和性

在 DPDK 多核任务绑定场景中,taskset 是最基础、最直接的 CPU 亲和性配置工具。它允许用户查看当前进程的 CPU 亲和性掩码,并将进程绑定到指定的 CPU 核心上运行。本章将系统讲解 taskset 的语法、常用操作及典型应用场景。

核心概念: CPU 亲和性(CPU Affinity)决定了一个进程或线程可以在哪些 CPU 核心上运行。通过 taskset 设置亲和性,可以避免进程在核心间频繁迁移,从而减少缓存失效和上下文切换开销。

3.1 taskset 基本语法

taskset 命令的语法格式如下:

taskset [options] mask command [argument...]
taskset [options] -p [mask] pid

参数说明:

参数 说明 示例
mask CPU 亲和性掩码,可用十六进制或 CPU 列表格式 0x01 或 0-3
-p 操作已运行的进程(需指定 PID) taskset -p 0x0f 1234
-c 使用 CPU 列表格式(如 0,2,4) taskset -c 0,2 ./app
command 要启动并绑定的命令 taskset 0x01 ./dpdk-worker
pid 目标进程 ID taskset -p 0x03 5678
提示: 掩码的每一位对应一个 CPU 核心(从 0 开始编号)。例如 0x03(二进制 0011)表示绑定到 CPU 0 和 CPU 1;0x0f(二进制 1111)表示绑定到 CPU 0~3。

3.2 查看进程亲和性

使用 taskset -p pid 可以查看指定进程当前的 CPU 亲和性掩码:

# 查看 PID 为 1234 的进程亲和性
$ taskset -p 1234
pid 1234's current affinity mask: 3

输出中的 3 是十六进制掩码,表示该进程可以运行在 CPU 0 和 CPU 1 上。如果需要更直观的 CPU 列表显示,可以加上 -c 选项:

$ taskset -cp 1234
pid 1234's current affinity list: 0,1

查看系统中所有 CPU 核心的编号:

$ lscpu | grep "CPU(s)"
CPU(s):              8
On-line CPU(s) list: 0-7
注意: 在 NUMA 架构系统中,CPU 核心编号可能不是连续的。建议先使用 lscpu 或 numactl --hardware 确认核心拓扑,再进行绑定操作。

3.3 设置进程亲和性

场景一:启动新进程并绑定到指定核心

# 将 dpdk-worker 绑定到 CPU 0 和 CPU 2
$ taskset -c 0,2 ./dpdk-worker

# 使用十六进制掩码:CPU 0 (bit0) + CPU 2 (bit2) = 0x05
$ taskset 0x05 ./dpdk-worker

场景二:修改已运行进程的亲和性

# 将 PID 5678 绑定到 CPU 0~3
$ taskset -p 0x0f 5678

# 使用 CPU 列表格式
$ taskset -cp 0-3 5678

场景三:绑定到单个核心(DPDK 常用)

# 将进程绑定到 CPU 3 上独占运行
$ taskset -c 3 ./dpdk-lcore-worker

3.4 绑定到指定 CPU 核心:典型流程

下图展示了使用 taskset 将 DPDK 工作进程绑定到指定核心的完整流程:

taskset 绑定 DPDK 工作进程流程图 1. 查看核心拓扑 2. 确定绑定核心 3. 启动/绑定进程 lscpu / numactl 选择空闲核心 taskset -c N ./app 4. 验证绑定结果:taskset -cp <PID> ✓ 绑定成功 ✗ 绑定失败 检查权限/核心编号

3.5 常用操作速查表

操作场景 命令示例 说明
查看进程亲和性 taskset -p 1234 显示十六进制掩码
查看进程亲和性(列表) taskset -cp 1234 显示 CPU 编号列表
启动并绑定到单核 taskset -c 3 ./app 绑定到 CPU 3
启动并绑定到多核 taskset -c 0,2,4 ./app 绑定到 CPU 0、2、4
修改运行中进程 taskset -p 0x0f 5678 将 PID 5678 绑定到 CPU 0~3
绑定到连续核心范围 taskset -c 0-3 ./app 绑定到 CPU 0 到 3
查看所有核心信息 lscpu | grep -E "CPU|Core|Socket" 确认核心拓扑

3.6 常见问题与避坑指南

  • 权限不足: 修改其他用户的进程亲和性需要 root 权限,使用 sudo 或切换为 root 用户。
  • 核心编号错误: 在 NUMA 系统中,核心编号可能不是从 0 开始连续排列,务必先使用 lscpu 确认。
  • 掩码格式混淆: taskset -c 0,2 和 taskset 0x05 效果相同,但 -c 更直观,推荐在脚本中使用。
  • 绑定后无法迁移: 一旦绑定,除非显式修改,否则进程不会自动迁移到其他核心。
  • 子进程继承: 使用 taskset 启动的进程,其子进程默认继承父进程的亲和性设置。
DPDK 最佳实践: 在 DPDK 应用中,通常将每个 lcore 绑定到独立的物理核心,避免超线程核心。例如在 8 核系统上,使用 taskset -c 0,2,4,6 ./dpdk-app 绑定到物理核心,跳过超线程核心 1,3,5,7。