Linux 如何绑定指定线程在某个固定CPU上

gcc version:5.4.0
Linux version: 4.4.0
之所以先说明版本,因为不同版本上很有可能有不同的问题。

绑定的方法主要是靠 setaffinity / getaffinity 一组方法来做的,其中有

#define _GNU_SOURCE
#include <sched.h>

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

#define _GNU_SOURCE
#include <pthread.h>

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, const cpu_set_t *cpuset);

其中的 CPU_SET 可以直接看 manual,但是我把它的一些使用放在下面:

#define _GNU_SOURCE
#include <sched.h>

void CPU_ZERO(cpu_set_t *set);                  // 清空 cpu_set
void CPU_SET(int cpu, cpu_set_t *set);        // 加入 \cpu 到 cpu_set
void CPU_CLR(int cpu, cpu_set_t *set);        // 删除 \cpu 从 cpu_set 中
int    CPU_ISSET(int cpu, cpu_set_t *set);     // 尝试 \cpu 是否在 cpu_set 中
int    CPU_COUNT(cpu_set_t *set);               // 将 cpu_set 中设置的 cpu 数量返回

一个使用 affinity 方法的 demo code:


#include <stdio.h>
#include <stdlib.h>
//#define __USE_GNU
#define _GNU_SOURCE
#include <time.h>
#include <sched.h>
#include <pthread.h>

void mybind_cpu(int cpu_id)
{
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(cpu_id, &mask);
    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0) {
        printf("Error: setaffinity()\n");
        exit(0);
    }
    return ;
}

void test_thread(void* cpu_id) {
    int cpuid = (int)(long)cpu_id;
    mybind_cpu(cpuid);
    printf("thread(%d) is running\n", (int)pthread_self());
    return ;
}

int main(void) 
{
    int res;
    void *thread_result;
    pthread_t test_thread_ctrl[10];
    int i = 0;
    for (i = 0; i < 10; ++i) {
        pthread_create(&(test_thread_ctrl[i]), NULL, (void*)test_thread, (void*)0);
    }
    for (i = 0; i < 10; ++i)
        res = pthread_join(test_thread_ctrl[i], &thread_result);
    (void)res;
    return 0;
}


这样用 gcc 编译会报错,错误是

bind_cpu.c:(.text+0x30): undefined reference to `CPU_ZERO'
bind_cpu.c:(.text+0x4c): undefined reference to `CPU_SET'
collect2: error: ld returned 1 exit status

查看 sched.h 文件会发现 CPU_ZERO 定义为(xshell上的文本太难拷贝了,我还是直接截图算了):

那么再引入 __USE_GNU 宏,又会报错:

然后我直接把这个函数的定义给注释掉了,就ok了,最后成功运行。

说明一下,虽然 affinity 这个单词只是暗示函数会让 thread 保证对某些 CPU 有亲和性,但是实际的函数定义处,却可以看到这句注释:

当然,怎么理解就见仁见智了。

来自10分钟后的更新。。。

搜了一下,stackoverflow上有人提到了,__locale_t 这个类型在 xlocale.h 文件里,而这个文件只包含在 string.h 内,并且只有打开 __USE_XOPEN2K8 才能看见,因此改了一下前面的头文件 include,加上:

#define __USE_XOPEN2K8
#include <string.h>

果然大功告成了!!!不用作死去改 glibc 的头文件了。

Reference:
stackoverflow: https://stackoverflow.com/questions/24738059/c-error-locale-t-has-not-been-declared

posted on 2018-03-29 20:14  daghlny  阅读(2652)  评论(0编辑  收藏  举报

导航