不管是线程还是进程,都是通过设置亲和性(affinity)来达到目的。对于进程一般是使用 sched_setaffinity
这个函数来实现.
与进程的情况相似,线程亲和性的设置和获取主要通过下面两个函数来实现:
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 ) ;
从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的以下宏来进行清除、设置以及判断:
1 2 3 4 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, const cpu_set_t *set) ;
cpu集可以认为是一个掩码,每个设置的位都对应一个可以合法调度的 cpu,而未设置的位则对应一个不可调度的 CPU。换而言之,线程都被绑定了,只能在那些对应位被设置了的处理器上运行。通常,掩码中的所有位都被置位了,也就是可以在所有的cpu中调度。
以下为测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sched.h> void *myfun (void *arg) { cpu_set_t mask; cpu_set_t get; char buf[256 ]; int i; int j; int num = sysconf (_SC_NPROCESSORS_CONF); printf ("system has %d processor(s)\n" , num); for (i = 0 ; i < num; i++) { CPU_ZERO (&mask); CPU_SET (i, &mask); if (pthread_setaffinity_np (pthread_self (), sizeof (mask), &mask) < 0 ) { fprintf (stderr, "set thread affinity failed\n" ); } CPU_ZERO (&get); if (pthread_getaffinity_np (pthread_self (), sizeof (get), &get) < 0 ) { fprintf (stderr, "get thread affinity failed\n" ); } for (j = 0 ; j < num; j++) { if (CPU_ISSET (j, &get)) { printf ("thread %d is running in processor %d\n" , (int )pthread_self (), j); } } j = 0 ; while (j++ < 100000000 ) { memset (buf, 0 , sizeof (buf)); } } pthread_exit (NULL ); }int main (int argc, char *argv[]) { pthread_t tid; if (pthread_create (&tid, NULL , (void *)myfun, NULL ) != 0 ) { fprintf (stderr, "thread create failed\n" ); return -1 ; } pthread_join (tid, NULL ); return 0 ; }