linux:获取、设置进程(线程)的cpu亲和性-尊龙官方平台

linux:获取、设置进程(线程)的cpu亲和性

el/2024/3/25 16:48:35

linux:设置进程(线程)的cpu亲和性


一、进程的cpu亲和性的获取(get)或者设置(set)

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

demo:主线程创建四个线程,获取主线程的cpu亲和性,设置四个非主线程的cpu亲和性

main.c

#define _gnu_source
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include pid_t gettid() {return syscall(sys_gettid);
}void *start_routine(void *arg)
{int thn = *((int *)arg);pid_t pid = gettid(); // lwppthread_t tid = pthread_self();long cpu_num = sysconf(_sc_nprocessors_onln);if (cpu_num <= 0) {printf("thn=%d,pid=%d,tid=%lu,get cpu info error:%ld\n",thn, pid, tid, cpu_num);return;}cpu_set_t cpu_set;cpu_zero(&cpu_set);cpu_set(thn%cpu_num, &cpu_set);int res = sched_setaffinity(0 /* or pid */, sizeof(cpu_set), &cpu_set);if (res != 0) {printf("thn=%d,pid=%d,tid=%lu,sched_setaffinity error:%d(%s)\n",thn, pid, tid, res, strerror(res));return;}printf("thn=%d,pid=%d,tid=%lu,bind cpu[%d] ok!\n",thn, pid, tid, thn%cpu_num);while (1)sleep(1);
}int main()
{int i0 = 0;pthread_t tid0;pthread_create(&tid0, null, start_routine, &i0);int i1 = 1;pthread_t tid1;pthread_create(&tid1, null, start_routine, &i1);int i2 = 2;pthread_t tid2;pthread_create(&tid2, null, start_routine, &i2);int i3 = 3;pthread_t tid3;pthread_create(&tid3, null, start_routine, &i3);cpu_set_t cpu_set;cpu_zero(&cpu_set);int res = sched_getaffinity(0 /* or getpid() */, sizeof(cpu_set), &cpu_set);if (res != 0) {printf("main: pid=%d,tid=%lu,sched_getaffinity error:%d(%s)\n",getpid(), pthread_self(), res, strerror(res));return;}int i = 0;for (; i < sizeof(cpu_set); i  ) {if (cpu_isset(i, &cpu_set)) {printf("main: pid=%d,tid=%lu,bind cpu[%d]\n", getpid(), pthread_self(), i);}}while (1)sleep(1);
}

编译运行:

[test1280@localhost 20190305]$ gcc -o main main.c -lpthread
[test1280@localhost 20190305]$ ./main
main: pid=31387,tid=140119163442944,bind cpu[0]
thn=3,pid=31391,tid=140119131965184,bind cpu[3] ok!
main: pid=31387,tid=140119163442944,bind cpu[1]
main: pid=31387,tid=140119163442944,bind cpu[2]
main: pid=31387,tid=140119163442944,bind cpu[3]
thn=1,pid=31389,tid=140119152944896,bind cpu[1] ok!
thn=0,pid=31388,tid=140119163434752,bind cpu[0] ok!
thn=2,pid=31390,tid=140119142455040,bind cpu[2] ok!
^c

主线程(pid=31387)创建了四个线程(pid=31388、31389、31390、31391)。

pid=31387 可运行在 cpu0、cpu1、cpu2、cpu3
pid=31388 可运行在 cpu0
pid=31389 可运行在 cpu1
pid=31390 可运行在 cpu2
pid=31391 可运行在 cpu3

[test1280@localhost 20190305]$ taskset -pc 31387
pid 31387's current affinity list: 0-3
[test1280@localhost 20190305]$ taskset -pc 31391
pid 31391's current affinity list: 3
[test1280@localhost 20190305]$ taskset -pc 31389
pid 31389's current affinity list: 1
[test1280@localhost 20190305]$ taskset -pc 31388
pid 31388's current affinity list: 0
[test1280@localhost 20190305]$ taskset -pc 31390
pid 31390's current affinity list: 2

通过 taskset 命令可进行验证。

关于 cpu_set_t 类型,类似于 fd_set(select),有几个宏可直接对“位集”进行操作:

void cpu_zero(cpu_set_t *set);
void cpu_set(int cpu, cpu_set_t *set);
void cpu_clr(int cpu, cpu_set_t *set);
int  cpu_isset(int cpu, cpu_set_t *set);
……
the affinity mask is actually a per-thread attribute that can be adjusted independently for each of the threads in a thread group.

cpu亲和性是线程级属性,能够被独立地(与其他线程无关)地设置或获取。

线程是最小的调度执行单元,理所应当地,是线程运行在某cpu之上,亲和性是线程的一个属性。

需要注意,这两个系统调用的第一个参数pid,都是内核分配的pid(tid、lwp),而非 pthread_t 类型。

准确地说,没有能设置、获取整个进程的cpu亲和性的接口,只有能设置、获取某线程的cpu亲和性的接口。


二、线程的cpu亲和性的获取(get)或者设置(set)

int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);

demo:主线程创建四个线程,获取主线程的cpu亲和性,设置四个非主线程的cpu亲和性

main.c

#define _gnu_source
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include pid_t gettid() {return syscall(sys_gettid);
}void *start_routine(void *arg)
{int thn = *((int *)arg);pid_t pid = gettid(); // lwppthread_t tid = pthread_self();long cpu_num = sysconf(_sc_nprocessors_onln);if (cpu_num <= 0) {printf("thn=%d,pid=%d,tid=%lu,get cpu info error:%ld\n",thn, pid, tid, cpu_num);return;}cpu_set_t cpu_set;cpu_zero(&cpu_set);cpu_set(thn%cpu_num, &cpu_set);int res = pthread_setaffinity_np(tid, sizeof(cpu_set), &cpu_set);if (res != 0) {printf("thn=%d,pid=%d,tid=%lu,pthread_setaffinity_np error:%d(%s)\n",thn, pid, tid, res, strerror(res));return;}printf("thn=%d,pid=%d,tid=%lu,bind cpu[%d] ok!\n",thn, pid, tid, thn%cpu_num);while (1)sleep(1);
}int main()
{int i0 = 0;pthread_t tid0;pthread_create(&tid0, null, start_routine, &i0);int i1 = 1;pthread_t tid1;pthread_create(&tid1, null, start_routine, &i1);int i2 = 2;pthread_t tid2;pthread_create(&tid2, null, start_routine, &i2);int i3 = 3;pthread_t tid3;pthread_create(&tid3, null, start_routine, &i3);cpu_set_t cpu_set;cpu_zero(&cpu_set);int res = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);if (res != 0) {printf("main: pid=%d,tid=%lu,pthread_getaffinity_nperror:%d(%s)\n",getpid(), pthread_self(), res, strerror(res));return;}int i = 0;for (; i < sizeof(cpu_set); i  ) {if (cpu_isset(i, &cpu_set)) {printf("main: pid=%d,tid=%lu,bind cpu[%d]\n", getpid(), pthread_self(), i);}}while (1)sleep(1);
}

运行输出:

[test1280@localhost 20190305]$ ./main
main: pid=31765,tid=140313705346816,bind cpu[0]
main: pid=31765,tid=140313705346816,bind cpu[1]
main: pid=31765,tid=140313705346816,bind cpu[2]
main: pid=31765,tid=140313705346816,bind cpu[3]
thn=0,pid=31766,tid=140313705338624,bind cpu[0] ok!
thn=1,pid=31767,tid=140313694848768,bind cpu[1] ok!
thn=3,pid=31769,tid=140313673869056,bind cpu[3] ok!
thn=2,pid=31768,tid=140313684358912,bind cpu[2] ok!
^c
[test1280@localhost 20190305]$ taskset -pc 31765
pid 31765's current affinity list: 0-3
[test1280@localhost 20190305]$ taskset -pc 31766
pid 31766's current affinity list: 0
[test1280@localhost 20190305]$ taskset -pc 31767
pid 31767's current affinity list: 1
[test1280@localhost 20190305]$ taskset -pc 31768
pid 31768's current affinity list: 2
[test1280@localhost 20190305]$ taskset -pc 31769
pid 31769's current affinity list: 3

pthread_setaffinity_np 以及 pthread_getaffinity_np 是 libpthread 库(man 3) 实现的接口,底层实现基于系统调用(man 2) sched_setaffinity 以及 sched_setscheduler。

man pthread_getaffinity_np
these functions are implemented on top of the sched_setaffinity(2) and sched_getaffinity(2) system calls.

既然是 libpthread 库实现的接口,使用的线程标识符也是 libpthread 库自定义的 pthread_t 类型,而非 pid_t。

libpthread 库实现的这两个接口是不可移植的,所以函数名带了 _np 后缀标识(non-portable)。

man pthread_getaffinity_np
these functions are non-standard gnu extensions; hence the suffix "_np" (non-portable) in the names.

通过 pthread_create 创建的线程将 继承 原线程的cpu亲和性属性值。

man pthread_getaffinity_np
a new thread created by pthread_create() inherits a copy of its creator’s cpu affinity mask.

参考:

1.https://www.cnblogs.com/wenqiang/p/6049978.html
2.https://www.cnblogs.com/lubinlew/p/cpu_affinity.html

相关:

1.https://blog.csdn.net/test1280/article/details/87993669
2.https://blog.csdn.net/test1280/article/details/87991302
3.https://blog.csdn.net/test1280/article/details/87974748


http://www.ngui.cc/el/5127076.html

相关文章

go:go-chassis 第三方依赖包问题

go:go-chassis 第三方依赖包问题 1.下载 go-chassis 源码 test1280 $ git clone https://github.com/go-chassis/go-chassis initialized empty git repository in /home/test1280/go-chassis/.git/ remote: enumerating objects: 53, done. remote: counting obj…

git:fatal: unable to find remote helper for 'https'

git:fatal: unable to find remote helper for ‘https’ 复现 test1280 $ git clone https://github.com/go-chassis/go-chassis cloning into go-chassis... fatal: unable to find remote helper for httpstest1280 $ echo $path /home/test1280/git/bin:/home…

c:strerror(或 inet_ntoa) 返回值默认整型截断导致进程核心转储 core dumped

c:strerror(或 inet_ntoa) 返回值默认整型截断导致进程核心转储 core dumped 测试环境: [test1280localhost ~]$ uname -a linux localhost.localdomain 2.6.32-642.el6.x86_64 #1 smp tue may 10 17:27:01 utc 2016 x86_64 x86…

windows:配置多网卡路由表(规则)

windows:配置多网卡路由表(规则) 有时出差到中国移动研究院,既要连接到内网指定服务器工作,又希望能连接外网随时能查一些资料。 但是内网和外网不通的,如何配置笔记本能实现多网卡路由? 前置…

c/c :linux select 1024 文件描述符限制

c/c:linux select 1024 文件描述符限制 通常来说,linux下select调用要求文件描述符的值小于1024,也就是说,fd set中的每个文件描述符的值域为:[0,1023]。 如果超过,linux下select调用会发生什么ÿ…

lua:使用元表实现的一种面向对象方法调用

lua:使用元表实现的一种面向对象方法调用 一、lua中的面向对象编程 lua中,面向对象编程主要是通过table来实现的。 lua中,定义对象及方法: 冒号定义,冒号引用 local obj {}function obj:setname(name)self.name …

go:源码的修改、调试

go:源码的修改、调试 需求: 1.通过修改go源码逻辑,实现想要的自定义功能。 例如:修改go的net/http等相关包的代码,内嵌针对http请求/应答的原始消息输出到日志,方便定位排查。 2.临时修改go源码逻辑&am…

linux:常用压缩及解压缩命令

linux:常用压缩及解压缩命令 后缀:tar解包:tar xf redis-4.0.10.tar打包:tar cf redis-4.0.10.tar redis-4.0.10说明:-c, --createcreate a new archive-x, --extract, --getextract files from an archive-f, --filea…

mysql:查看mysql版本号

mysql:查看mysql版本号 方法一**【推荐】**: mysql> select version(); ----------- | version() | ----------- | 8.0.15 | ----------- 1 row in set (0.00 sec)方法二: mysql> status -------------- mysql ver 8.0.15 for l…

mysql:常用基本操作命令集

mysql:常用基本操作命令集 客户端使用帮助 $ mysql --help ……-p, --password[name] password to use when connecting to server. if password isnot given its asked from the tty.-p, --port# port number to use for connection or 0 for default to,…
网站地图