转载自 https://www.cnblogs.com/swey/p/4469722.html
为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程。
Linux提供一个接口,可以将进程绑定到特定的CPU:
#define _GNU_SOURCE //这行必须在下面这include之前,否则CPU_SET不认识
#include
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
#include
#include
#include
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,线程也可以。Linux提供一个接口,可以将线程绑定到特定的CPU:
#include
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
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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,¶m);
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,¶m);
pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);
#endif
//modify current process's all pthread
//这个函数在内核里也可以用,设置当前task sched_setscheduler(current, SCHED_FIFO, ¶m);
ret = sched_setscheduler(getpid(),SCHED_RR,¶m);
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);