为何isolcpus隔离的CPU核上能同时运行主线程与pthreads?
关于isolcpus隔离CPU后线程仍能运行在该CPU上的疑问解答
环境与代码说明
- 系统配置:6核Linux系统,已通过grub配置文件
/etc/default/grub中的参数GRUB_CMDLINE_LINUX_DEFAULT="quiet isolcpus=0 nohz_full=1"将CPU0从内核调度器隔离,且cat /sys/devices/system/cpu/isolated命令验证隔离状态正常 - 编译命令:
gcc -pthread ... - 测试代码:
#define _GNU_SOURCE #include <stdio.h> #include <pthread.h> #include <sched.h> #include <unistd.h> void *thread(void *ptr) { for(;;) { show_curr_cpu("pthread"); sleep(2); } } void show_curr_cpu(char *str) { unsigned int cpu, node; if (getcpu(&cpu, &node) != 0) { perror("getcpu"); return; } printf("[%s]Current CPU: %u\n", str, cpu); } int main(void) { show_curr_cpu("main-bfr"); cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); /* 0号CPU核心 */ pthread_t current_thread = pthread_self(); pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); show_curr_cpu("main-aft"); pthread_t thread1; int thr = 1; if (pthread_create(&thread1, NULL, thread, (void *) thr)) { perror("pthread_create"); return -1; } for(;;) { show_curr_cpu("main"); sleep(2); } }
现象与疑问
根据isolcpus的定义:
将指定编号的CPU从通用内核SMP平衡与调度算法中移除
另有资料说明:
isolcpus内核参数指定的CPU集合会被进程调度器忽略,调度器不会将进程放置到这些CPU上,也不会进行进程迁移操作。
但运行代码后得到结果:
[main-bfr]Current CPU: 5 [main-aft]Current CPU: 0 [main]Current CPU: 0 [pthread]Current CPU: 0 [main]Current CPU: 0 [pthread]Current CPU: 0 ^C
主线程和pthread都运行在CPU0上,疑问在于:为何这两个线程能在隔离的CPU0上共享运行,且看起来调度器没参与?
原因解析
isolcpus限制的是“自动调度”,而非“禁止绑定”
isolcpus只是让内核调度器不会自动将未指定亲和性的进程/线程调度到隔离CPU上,也不会主动把隔离CPU上的进程迁移走。但它完全允许用户通过pthread_setaffinity_np或sched_setaffinity这类手动设置亲和性的接口,把进程/线程绑定到隔离CPU上——你的代码里正是这么做的,主线程手动绑定到了CPU0。新线程会继承父线程的CPU亲和性
你创建的pthread是主线程的子线程,默认会继承主线程的CPU亲和性配置,所以它也被绑定到了CPU0上,自然会在这个核心上运行。调度器依然在隔离CPU上工作
你看到两个线程在CPU0上交替输出,说明调度器依然在管理这个核心上的线程时间片——isolcpus只是不让调度器把其他无关进程塞到这个核心,但对于已经绑定过来的线程,调度器还是会正常进行线程切换、时间片分配等操作,并不是“调度器未参与其中”。
内容的提问来源于stack exchange,提问作者red0ct
相关产品推荐
相关产品推荐

