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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM