最近需要用ejtag调试CRIU程序中遇到的BUSERROR的问题,环境准备的第一件事就是要让被调试的程序独占一个处理器(核)。 怎么做呢? 方法如下:
一、准备工作:隔离出cpu某核(此核不再参与进程调度)
此步操作需要root权限才可以完成。
具体修改在/ boot/boot.cf的kernel列最末尾加上isolcpus=x,y,… (代表将CPUx CPUy隔离)
title 'Loongnix 1.0 (Loongson)'
...
args root=/dev/sda3 console=tty console=ttyS0,115200 rw isolcpus=0
这里,我设置了把cpu0隔离出去,然后重启电脑后配置即可生效。
这里isolcpus是传给内核的参数,意为通知内核进程调度模块处理器0不参与进程调度(就算是其他处理器已经负载100%)。如果你要隔离多个处理器可以使用逗号分割,例如我要隔离0号和3号处理器,那么可以写成 isolcpus=0,3
/boot/EFI/BOOT/grub.cfg
那么如何验证此修改起效了呢?
验证隔离的方式
1、 编写用cpu烤鸡蛋的程序
/**demo.c**/
#include <pthread.h>
void* thread_f(void * i){
//为了能让cpu可以把鸡蛋烤熟,必须确保你的程序是cpu密集型,不要有任何io操作
//我这里可是连printf语句都没有的。
while(1){}
return NULL;
}
int main(int argc,char* argv[]){
double count = 0;
pthread_t t0;
pthread_t t1;
pthread_t t2;
pthread_t t3;
if(pthread_create(&t0, NULL, thread_f, NULL) == -1){
puts("fail to create pthread t0");
return 0;
}
if(pthread_create(&t1, NULL, thread_f, NULL) == -1){
puts("fail to create pthread t1");
return 0;
}
if(pthread_create(&t2, NULL, thread_f, NULL) == -1){
puts("fail to create pthread t2");
return 0;
}
if(pthread_create(&t3, NULL, thread_f, NULL) == -1){
puts("fail to create pthread t3");
return 0;
}
int ret = pthread_join(t0, NULL);
return 0;
}
我当前主机是4核4线程的处理器,所以这里我是启动了4个线程去执行一段cpu密集型操作。如果没有isolcpus=0的限制,这个程序可以把4个核全部跑满。接下来编译demo.c
$ gcc demo.c -pthread -o demo
2、 运行用cpu烤鸡蛋的程序并验证结果
$ ./demo &
[1] 10451
然后使用mpstat命令查看所有cpu使用情况
$ mpstat -P ALL 4
Linux 3.10.0+ (localhost) 2019年09月26日 _mips64_ (4 CPU)
17时45分57秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
17时46分01秒 all 74.56 0.00 0.44 0.00 0.00 0.06 0.00 0.00 0.00 24.94
17时46分01秒 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
17时46分01秒 1 98.75 0.00 1.25 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17时46分01秒 2 99.75 0.00 0.25 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17时46分01秒 3 99.75 0.00 0.25 0.00 0.00 0.00 0.00 0.00 0.00 0.00
可以看到,当期主机是4个处理器。上面的demo程序启动4个cpu密集型线程,理论上可以把4个处理器全部跑满,当是看上面的idle列,cpu1、cpu2和cpu3都已经为0,说明已经满负荷工作,而cpu0却还是idle 100,它已经被内核处理器调度策略排除运算了。也就说明上面的isolcpus=0设置成功。
注意.:如果你的机器没有mpstat工具,需要执行如下命令即可
$ yum install -y sysstat
二、设置程序demo独占处理器CPU0
如何把一个进程或线程绑定(亲和)到固定的处理器,方法很多,可以在代码里设定,可以在程序启动时或启动后设定。
代码里设置的方法:
int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); //设定某个进程的CPU亲和度
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);//设定某个线程的CPU亲和度
命令行的设置方法有两种(使用taskset):
方法1、运行时指定:
taskset < cpu列表 > [命令]
例如:我想把demo应用运行在cpu0核上,那么命令是
taskset -c cpu0 demo
方法2、运行后指定:
taskset < cpu列表 > [PID]
例如:demo程序已经在运行且pid为7013。那么我要设置此进程只能运行在cpu0核上。命令如下
taskset -c cpu0 7013
注意.:在龙芯平台上,运行后的taskset无效。
我们使用运行时指定方式
$ taskset -c 0 ./demo &
[2] 11863
然后再次使用mpstat查看cpu占用率
]$ mpstat -P ALL 4
Linux 3.10.0+ (localhost) 2019年09月26日 _mips64_ (4 CPU)
18时04分47秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
18时04分51秒 all 29.12 0.00 0.38 0.00 0.00 0.00 0.00 0.00 0.00 70.51
18时04分51秒 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
18时04分51秒 1 0.50 0.00 0.50 0.00 0.00 0.00 0.00 0.00 0.00 99.00
18时04分51秒 2 9.05 0.00 0.75 0.00 0.00 0.00 0.00 0.00 0.00 90.20
18时04分51秒 3 6.28 0.00 0.50 0.00 0.00 0.00 0.00 0.00 0.00 93.22
看到没?此时cpu0已经满负荷工作了(demo进程里的4个线程都运行在了cpu0上)。其他cpu1-cpu3却悠闲的很呢。