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