Linux进程或线程绑定到CPU+修改优先级

 

转载自 https://www.cnblogs.com/swey/p/4469722.html

为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程。

进程绑定到CPU

Linux提供一个接口,可以将进程绑定到特定的CPU:

#define _GNU_SOURCE         //这行必须在下面这include之前,否则CPU_SET不认识

#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, cpu_set_t *mask);

参数

pid:进程的id号,如果pid为0,则表示本进程

cpusetsize:mask的大小

mask:运行进程的CPU,可以通过以下函数操作mask

#define CPU_SET(cpu, cpusetp) //设置cpu

#define CPU_CLR(cpu, cpusetp) //删除cpu

#define CPU_ISSET(cpu, cpusetp) //判断cpu

#define CPU_ZERO(cpusetp) //初始化为0

示例代码

复制代码

#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <sched.h>
 
void WasteTime()
{
    int abc = 10000000;
    while(abc--)
    {
        int tmp = 10000*10000;
    }
    sleep(1);

}

int main(int argc, char **argv)
{
    cpu_set_t mask;
    while(1)
    {
 
        CPU_ZERO(&mask);
        CPU_SET(0, &mask); 
        if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            perror("sched_setaffinity");
        }
        WasteTime();
 
        CPU_ZERO(&mask);
        CPU_SET(1, &mask); 
        if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            perror("sched_setaffinity");
        }
        WasteTime();
     
        CPU_ZERO(&mask);
        CPU_SET(2, &mask); 
        if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            perror("sched_setaffinity");
        }
        WasteTime();
     
        CPU_ZERO(&mask);
        CPU_SET(3, &mask); 
        if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            perror("sched_setaffinity");
        }
        WasteTime();
    }
}

复制代码

测试

编译之后运行程序,输入命令top -p 进程id,输入f(增加或者删除top命令显示列),上下按键移动光标到P (Last used CPU),按D键让其高亮。然后按q键退出即可。可以看到P这列出来了。 (kernel 4.9)

 

线程绑定到CPU

不仅仅进程可以绑定到CPU,线程也可以。Linux提供一个接口,可以将线程绑定到特定的CPU:

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

该接口与进程绑定到CPU的接口的使用方法基本一致。

当进程绑定到特定的CPU之后,线程还是可以绑定到其他的CPU的,没有冲突。

示例代码

复制代码

#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <unistd.h>
#include <sched.h>

void WasteTime()
{
    int abc = 10000000;
    while(abc--)
    {
        int tmp = 10000*10000;
    }
    sleep(1);

}

void *thread_func(void *param)
{
    cpu_set_t mask;
    while(1)
    {
         CPU_ZERO(&mask);
        CPU_SET(1, &mask); 

        if (pthread_setaffinity_np(pthread_self(), sizeof(mask),
            &mask) < 0) {
            perror("pthread_setaffinity_np");
        }
 
        WasteTime();

         CPU_ZERO(&mask);
        CPU_SET(2, &mask); 
        if (pthread_setaffinity_np(pthread_self(), sizeof(mask),
            &mask) < 0) {
            perror("pthread_setaffinity_np");
        }

        WasteTime();
    }
}
 
void *thread_func1(void *param)
{
    cpu_set_t mask;
    while(1)
    {
         CPU_ZERO(&mask);
        CPU_SET(3, &mask); 

        if (pthread_setaffinity_np(pthread_self(), sizeof(mask),
            &mask) < 0) {
            perror("pthread_setaffinity_np");
        }
 
        WasteTime();

         CPU_ZERO(&mask);
        CPU_SET(4, &mask); 
        if (pthread_setaffinity_np(pthread_self(), sizeof(mask),
            &mask) < 0) {
            perror("pthread_setaffinity_np");
        }

        WasteTime();
    }
}
 
int main(int argc, char *argv[])
{
    cpu_set_t mask;
     CPU_ZERO(&mask);
    CPU_SET(0, &mask); 
    if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
        perror("sched_setaffinity");
    }

    pthread_t my_thread;
 
    if (pthread_create(&my_thread, NULL, thread_func,
        NULL) != 0) {
        perror("pthread_create");
    }
    if (pthread_create(&my_thread, NULL, thread_func1,
        NULL) != 0) {
        perror("pthread_create");
    }
    while(1) { WasteTime(); }
    pthread_exit(NULL);

}

复制代码

测试

编译之后运行程序,输入命令top -p 进程id(这里可以时task id,一个进程下可以有多个task,默认名字和进程一样,可进proc/pid/task下查看当前进程有多少个task),输入f(增加或者删除top命令显示列),上下按键移动光标到P (Last used CPU),按D键让其高亮。然后按q键退出即可。可以看到P这列出来了。

top命令行下,按下1,可以显示各个core的使用情况

调整优先级

可参考 http://blog.chinaunix.net/uid-24774106-id-3379478.html

            https://bbs.csdn.net/topics/340030105

在用户层或者应用层,1表示优先级最低,99表示优先级最高。但是在内核中,[0,99]表示的实时进程的优先级,0最高,99最低。[100,139]是普通进程折腾的范围。应用层比较天真率直,就看大小,数字大,则优先级高。ps查看进程的优先级也是如此。有意思的是,应用层实时进程最高优先级的99,在ps看进程优先级的时候,输出的是139.

实时进程的优先级设置可以通过sched_setsheduler设置,也可以通过sched_setparam设置优先级的大小。

线程的优先级,目前只清楚可通过下面在pthread_create时设定,线程体内怎么设置还不清楚。

  
#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>


static void *thread_entry(void *arg)
{

    int i = *(int *)arg;
    printf("thread_entry i=%d\n",i);
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) < 0) {
        perror("sched_setaffinity");
    }

    int policy;
    struct sched_param param;
    pthread_getschedparam(pthread_self(),&policy,&param);
    printf("policy=%d  priority=%d\n",policy,param.sched_priority);

    for(int i=0;i<1000;i++){
        for(int j=0;j<1000000;j++){
        }

        pthread_attr_init(&attr);
    }
    printf("thread %d exit\n",i);
    pthread_exit((void *)0);
}

static int threadnum[4] = {0,1,2,3};


void main (){
        int ret;

        struct sched_param param;
        param.sched_priority=51;

#if 0
        //only modify the pthread which use this attr
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        
        pthread_attr_setschedpolicy(&attr,SCHED_RR);
        pthread_attr_setschedparam(&attr,&param);
        pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);
#endif

        //modify current process's  all pthread

        //这个函数在内核里也可以用,设置当前task   sched_setscheduler(current, SCHED_FIFO, &param);
        ret = sched_setscheduler(getpid(),SCHED_RR,&param);     

        pthread_t *thread =(pthread_t *) malloc(sizeof(pthread_t)*4);
        for (int i = 0; i < 3; i++) {
                pthread_create(&thread[i], NULL, thread_entry, (void *)&threadnum[i]);
        }
        pthread_create(&thread[3], NULL, thread_entry, (void *)&threadnum[3]);

        for (int i = 0; i < 4; i++) {
                ret = pthread_join(thread[i], NULL);
                if (ret != 0) {
                        printf("cpuwhile thread%d failed,error=%d\n", i,ret);
                } else {
                        printf("cpuwhile thread%d test success\n", i);
                }
        }


        //pthread_attr_destroy(&attr);

        printf("free!");

        if(thread != NULL)
                free(thread);


                               

猜你喜欢

转载自blog.csdn.net/chenpuo/article/details/82465336