线程绑定CPU核的意义:

在多核CPU中合理的调度线程在各个核上运行可以获得更高的性能。在多线程编程中,每个线程处理的任务优先级是不一样的,对于要求实时性比较高的线程或者是主线程,对于这种线程我们可以在创建线程时指定其绑定到某个CPU核上,以后这个核就专门处理该线程。这样可以使得该线程的任务可以得到较快的处理,特别是和用户直接交互的任务,较短的响应时间可以提升用户的体验感。

绑定的过程:

几个重要的宏操作:

一个线程的CPU亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作:

CPU_ZERO() 清空一个集合
CPU_SET()与CPU_CLR()分别对将一个给定的CPU号加到一个集合或者从一个集合中去掉.
CPU_ISSET()检查一个CPU号是否在这个集合中

设置获取线程CPU亲和力状态:

(1)sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
该函数设置线程为pid的这个线程,让它运行在mask所设定的CPU上.如果pid的值为0,则表示指定的是当前线程,使当前线程运行在mask所设定的那些CPU上.第二个参数cpusetsize是mask所指定的数的长度.通常设定为sizeof(cpu_set_t).如果当前pid所指定的线程此时没有运行在mask所指定的任意一个CPU上,则该指定的线程会从其它CPU上迁移到mask的指定的一个CPU上运行.
(2)sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
该函数获得pid所指示的线程的CPU位掩码,并将该掩码返回到mask所指向的结构中.即获得指定pid当前可以运行在哪些CPU上.同样,如果pid的值为0.也表示的是当前进程

简单的实例:

#此代码不完整,只是帮助理解绑定过程
#在创建线程时添加以下代码,可以将该线程绑定到1核

cpu_set_t mask;
#将掩码清零
CPU_ZERO(&mask);
#将1添加到掩码中
CPU_SET(1, &mask);

#将本线程绑定到1核
sched_setaffinity(0, sizeof(cpu_set_t), &mask);

如何查看线程是否运行在指定的核上:

补充:

实际工作中,为了方便查看线程的情况,会在创建线程时将相关信息保存到一个文件中,需要时用cat命令查看, 内容包括创建了哪些线程、线程名称、线程id和pid、绑定的CPU核、优先级、调度方式等。

用top命令查看:

top -d 2:查看线程的运行情况和CPU状态
按’h’ 和 1:在上一句的基础上可以查看更详细的信息。
从文件中得到线程pid和ppid,通过top命令,查看线程在哪个CPU核上运行,验证核绑定的核是否一样。