Linux内核的三种调度策略.docx
《Linux内核的三种调度策略.docx》由会员分享,可在线阅读,更多相关《Linux内核的三种调度策略.docx(13页珍藏版)》请在冰点文库上搜索。
Linux内核的三种调度策略
Linux内核的三种调度策略:
1,SCHED_OTHER分时调度策略,
2,SCHED_FIFO实时调度策略,先到先服务。
一旦占用cpu则一直运行。
一直运行直到有更高优先级任务到达或自己放弃
3,SCHED_RR实时调度策略,时间片轮转。
当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。
放在队列尾保证了所有具有相同优先级的RR任务的调度公平
Linux线程优先级设置
首先,可以通过以下两个函数来获得线程可以设置的最高和最低优先级,函数中的策略即上述三种策略的宏定义:
intsched_get_priority_max(intpolicy);
intsched_get_priority_min(intpolicy);
SCHED_OTHER是不支持优先级使用的,而SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高。
设置和获取优先级通过以下两个函数
intpthread_attr_setschedparam(pthread_attr_t*attr,conststructsched_param*param);
intpthread_attr_getschedparam(constpthread_attr_t*attr,structsched_param*param);
param.sched_priority=51;//设置优先级
系统创建线程时,默认的线程是SCHED_OTHER。
所以如果我们要改变线程的调度策略的话,可以通过下面的这个函数实现。
intpthread_attr_setschedpolicy(pthread_attr_t*attr,intpolicy);
上面的param使用了下面的这个数据结构:
structsched_param
{
int__sched_priority;//所要设定的线程优先级
};
我们可以通过下面的测试程序来说明,我们自己使用的系统的支持的优先级:
#include
#include
#include
#include
staticintget_thread_policy(pthread_attr_t*attr)
{
intpolicy;
intrs=pthread_attr_getschedpolicy(attr,&policy);
assert(rs==0);
switch(policy)
{
caseSCHED_FIFO:
printf("policy=SCHED_FIFO\n");
break;
caseSCHED_RR:
printf("policy=SCHED_RR");
break;
caseSCHED_OTHER:
printf("policy=SCHED_OTHER\n");
break;
default:
printf("policy=UNKNOWN\n");
break;
}
returnpolicy;
}
staticvoidshow_thread_priority(pthread_attr_t*attr,intpolicy)
{
intpriority=sched_get_priority_max(policy);
assert(priority!
=-1);
printf("max_priority=%d\n",priority);
priority=sched_get_priority_min(policy);
assert(priority!
=-1);
printf("min_priority=%d\n",priority);
}
staticintget_thread_priority(pthread_attr_t*attr)
{
structsched_paramparam;
intrs=pthread_attr_getschedparam(attr,¶m);
assert(rs==0);
printf("priority=%d",param.__sched_priority);
returnparam.__sched_priority;
}
staticvoidset_thread_policy(pthread_attr_t*attr,intpolicy)
{
intrs=pthread_attr_setschedpolicy(attr,policy);
assert(rs==0);
get_thread_policy(attr);
}
intmain(void)
{
pthread_attr_tattr;
structsched_paramsched;
intrs;
rs=pthread_attr_init(&attr);
assert(rs==0);
intpolicy=get_thread_policy(&attr);
printf("Showcurrentconfigurationofpriority\n");
show_thread_priority(&attr,policy);
printf("showSCHED_FIFOofpriority\n");
show_thread_priority(&attr,SCHED_FIFO);
printf("showSCHED_RRofpriority\n");
show_thread_priority(&attr,SCHED_RR);
printf("showpriorityofcurrentthread\n");
intpriority=get_thread_priority(&attr);
printf("Setthreadpolicy\n");
printf("setSCHED_FIFOpolicy\n");
set_thread_policy(&attr,SCHED_FIFO);
printf("setSCHED_RRpolicy\n");
set_thread_policy(&attr,SCHED_RR);
printf("Restorecurrentpolicy\n");
set_thread_policy(&attr,policy);
rs=pthread_attr_destroy(&attr);
assert(rs==0);
return0;
}
下面是测试程序的运行结果:
policy=SCHED_OTHER
Showcurrentconfigurationofpriority
max_priority=0
min_priority=0
showSCHED_FIFOofpriority
max_priority=99
min_priority=1
showSCHED_RRofpriority
max_priority=99
min_priority=1
showpriorityofcurrentthread
priority=0Setthreadpolicy
setSCHED_FIFOpolicy
policy=SCHED_FIFO
setSCHED_RRpolicy
policy=SCHED_RRRestorecurrentpolicy
policy=SCHED_OTHER
Linux线程调度策略与优先级
(二)
上一篇文章介绍了Linux下的调度策略和优先级,在Ubuntu09.10上的一些特性,这里测试一下其中的两种特性,SCHED_OTHER和SCHED_RR,还有就是优先级的问题,是不是能够保证,高优先级的线程,就可以保证先运行。
下面的这个测试程序,创建了三个线程,默认创建的线程的调度策略是SCHED_OTHER,其余的两个线程的调度策略设置成SCHED_RR。
我的Linux的内核版本是2.6.31。
SCHED_RR是根据时间片来确定线程的调度。
时间片用完了,不管这个线程的优先级有多高都不会在运行,而是进入就绪队列中,等待下一个时间片的到了,那这个时间片到底要持续多长时间?
在《深入理解Linux内核》中的第七章进程调度中,是这样描诉的,Linux采取单凭经验的方法,即选择尽可能长、同时能保持良好相应时间的一个时间片。
这里也没有给出一个具体的时间来,可能会根据不同的CPU来定,还有就是多CPU的情况。
#include
#include
#include
#include
voidThread1()
{
sleep
(1);
inti,j;
intpolicy;
structsched_paramparam;
pthread_getschedparam(pthread_self(),&policy,¶m);
if(policy==SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy==SCHED_RR);
printf("SCHED_RR1\n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");
for(i=1;i<10;i++)
{
for(j=1;j<5000000;j++)
{
}
printf("thread1\n");
}
printf("Pthread1exit\n");
}
voidThread2()
{
sleep
(1);
inti,j,m;
intpolicy;
structsched_paramparam;
pthread_getschedparam(pthread_self(),&policy,¶m);
if(policy==SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy==SCHED_RR);
printf("SCHED_RR\n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");
for(i=1;i<10;i++)
{
for(j=1;j<5000000;j++)
{
}
printf("thread2\n");
}
printf("Pthread2exit\n");
}
voidThread3()
{
sleep
(1);
inti,j;
intpolicy;
structsched_paramparam;
pthread_getschedparam(pthread_self(),&policy,¶m);
if(policy==SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy==SCHED_RR)
printf("SCHED_RR\n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");
for(i=1;i<10;i++)
{
for(j=1;j<5000000;j++)
{
}
printf("thread3\n");
}
printf("Pthread3exit\n");
}
intmain()
{
inti;
i=getuid();
if(i==0)
printf("Thecurrentuserisroot\n");
else
printf("Thecurrentuserisnotroot\n");
pthread_tppid1,ppid2,ppid3;
structsched_paramparam;
pthread_attr_tattr,attr1,attr2;
pthread_attr_init(&attr1);
pthread_attr_init(&attr);
pthread_attr_init(&attr2);
param.sched_priority=51;
pthread_attr_setschedpolicy(&attr2,SCHED_RR);
pthread_attr_setschedparam(&attr2,¶m);
pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED);//要使优先级其作用必须要有这句话
param.sched_priority=21;
pthread_attr_setschedpolicy(&attr1,SCHED_RR);
pthread_attr_setschedparam(&attr1,¶m);
pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);
pthread_create(&ppid3,&attr,(void*)Thread3,NULL);
pthread_create(&ppid2,&attr1,(void*)Thread2,NULL);
pthread_create(&ppid1,&attr2,(void*)Thread1,NULL);
pthread_join(ppid3,NULL);
pthread_join(ppid2,NULL);
pthread_join(ppid1,NULL);
pthread_attr_destroy(&attr2);
pthread_attr_destroy(&attr1);
return0;
}
下面是该程序的其中之一的运行结果:
sudo./prio_test
Thecurrentuserisroot
SCHED_OTHER
SCHED_RR
SCHED_RR1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
Pthread1exit
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
Pthread2exit
thread3
thread3
thread3
thread3
thread3
thread3
thread3
thread3
thread3
Pthread3exit
这里我们可以看到,由于线程3的调度策略是SCHED_OTHER,而线程2的调度策略是SCHED_RR,所以,在Thread3中,线程3被线程1,线程2给抢占了。
由于线程1的优先级大于线程2的优先级,所以,在线程1以先于线程2运行,不过,这里线程2有一部分代码还是先于线程1运行了。
我原以为,只要线程的优先级高,就会一定先运行,其实,这样的理解是片面的,特别是在SMP的PC机上更会增加其不确定性。
其实,普通进程的调度,是CPU根据进程优先级算出时间片,这样并不能一定保证高优先级的进程一定先运行,只不过和优先级低的进程相比,通常优先级较高的进程获得的CPU时间片会更长而已。
其实,如果要想保证一个线程运行完在运行另一个线程的话,就要使用多线程的同步技术,信号量,条件变量等方法。
而不是绝对依靠优先级的高低,来保证。
不过,从运行的结果上,我们可以看到,调度策略为SCHED_RR的线程1,线程2确实抢占了调度策略为SCHED_OTHER的线程3。
这个是可以理解的,由于SCHER_RR是实时调度策略。
只有在下述事件之一发生时,实时进程才会被另外一个进程取代。
(1)进程被另外一个具有更高实时优先级的实时进程抢占。
(2)进程执行了阻塞操作并进入睡眠
(3)进程停止(处于TASK_STOPPED或TASK_TRACED状态)或被杀死。
(4)进程通过调用系统调用sched_yield(),自愿放弃CPU。
(5)进程基于时间片轮转的实时进程(SCHED_RR),而且用完了它的时间片。
基于时间片轮转的实时进程是,不是真正的改变进程的优先级,而是改变进程的基本时间片的长度。
所以基于时间片轮转的进程调度,并不能保证高优先级的进程先运行。
下面是另一种运行结果:
sudo./prio_test
Thecurrentuserisroot
SCHED_OTHER
SCHED_RR1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
thread1
Pthread1exit
SCHED_RR
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
thread2
Pthread2exit
thread3
thread3
thread3
thread3
thread3
thread3
thread3
thread3
thread3
Pthread3exit
可以看出并没有每一次都保证高优先级的线程先运行。