专栏名称: Linux爱好者
伯乐在线旗下账号,「Linux爱好者」专注分享 Linux/Unix 相关内容,包括:工具资源、使用技巧、课程书籍等。
相关文章推荐
Linux就该这么学  ·  这几个 CMD 网络排障命令,效率原地起飞! ·  12 小时前  
Linux爱好者  ·  阿里P8跌落神坛⋯⋯ ​​​ ·  3 天前  
Linux爱好者  ·  Cursor重磅上线Claude ... ·  3 天前  
Linux就该这么学  ·  手把手教学:Nginx ... ·  昨天  
Linux就该这么学  ·  几种 Window 系统测试 UDP 的方法 ·  2 天前  
51好读  ›  专栏  ›  Linux爱好者

进程怎么绑定 CPU

Linux爱好者  · 公众号  · linux  · 2025-03-16 09:21

正文

把进程绑定到某个 CPU 上运行是怎么实现的?

首先,我们先来了解下将进程与 CPU 进行绑定的好处。

进程绑定 CPU 的好处:在多核 CPU 结构中,每个核心有各自的L1、L2缓存,而L3缓存是共用的。如果一个进程在核心间来回切换,各个核心的缓存命中率就会受到影响。相反如果进程不管如何调度,都始终可以在一个核心上执行,那么其数据的L1、L2 缓存的命中率可以显著提高。

所以,将进程与 CPU 进行绑定可以提高 CPU 缓存的命中率,从而提高性能。而进程与 CPU 绑定被称为: CPU 亲和性

设置进程的 CPU 亲和性

前面介绍了进程与 CPU 绑定的好处后,现在来介绍一下在 Linux 系统下怎么将进程与 CPU 进行绑定的(也就是设置进程的 CPU 亲和性)。

Linux 系统提供了一个名为 sched_setaffinity 的系统调用,此系统调用可以设置进程的 CPU 亲和性。我们来看看 sched_setaffinity 系统调用的原型:

int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);

下面介绍一下 sched_setaffinity 系统调用各个参数的作用:

  • pid :进程ID,也就是要进行绑定 CPU 的进程ID。
  • cpusetsize :mask 参数所指向的 CPU 集合的大小。
  • mask :与进程进行绑定的 CPU 集合(由于一个进程可以绑定到多个 CPU 上运行)。

参数 mask 的类型为 cpu_set_t ,而 cpu_set_t 是一个位图,位图的每个位表示一个 CPU,如下图所示:



例如,将 cpu_set_t 的第0位设置为1,表示将进程绑定到 CPU0 上运行,当然我们可以将进程绑定到多个 CPU 上运行。

我们通过一个例子来介绍怎么通过 sched_setaffinity 系统调用来设置进程的 CPU 亲和性:

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    cpu_set_t cpuset;

    CPU_ZERO(&cpuset);    // 初始化CPU集合,将 cpuset 置为空
    CPU_SET(2, &cpuset);  // 将本进程绑定到 CPU2 上

    // 设置进程的 CPU 亲和性
    if (sched_setaffinity(0sizeof(cpuset), &cpuset) == -1) {
        printf("Set CPU affinity failed, error: %s\n", strerror(errno));
        return-1
    }

    return0;
}

CPU 亲和性实现

知道怎么设置进程的 CPU 亲和性后,现在我们来分析一下 Linux 内核是怎样实现 CPU 亲和性功能的。

本文使用的 Linux 内核版本为 2.6.23

Linux 内核为每个 CPU 定义了一个类型为 struct rq 可运行的进程队列 ,也就是说,每个 CPU 都拥有一个独立的可运行进程队列。

一般来说,CPU 只会从属于自己的可运行进程队列中选择一个进程来运行。也就是说,CPU0 只会从属于 CPU0 的可运行队列中选择一个进程来运行,而绝不会从 CPU1 的可运行队列中获取。

所以,从上面的信息中可以分析出,要将进程绑定到某个 CPU 上运行,只需要将进程放置到其所属的 可运行进程队列 中即可。

下面我们来分析一下 sched_setaffinity 系统调用的实现, sched_setaffinity 系统调用的调用链如下:

sys_sched_setaffinity()
└→ sched_setaffinity()
   └→ set_cpus_allowed()
      └→ migrate_task()

从上面的调用链可以看出, sched_setaffinity 系统调用最终会调用 migrate_task 函数来完成进程与 CPU 进行绑定的工作,我们来分析一下 migrate_task 函数的实现:

static int
migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
{
    struct rq






请到「今天看啥」查看全文