sched.h文件中定义了几种调度策略
/* Scheduling algorithms. */
#define SCHED_OTHER 0
#define SCHED_FIFO 1
#define SCHED_RR 2
SCHED_OTHER:非实时调度,分时调度。通过pthread_create创建,但属性参数传递NULL创建的线程默认以SCHED_OTHER方式创建。使用CFS调度器(Linux2.6.23引入作为默认用户进程分时调度器),时间片是动态的,使用红黑树取代了传统运行队列来管理任务,使CPU消耗比较小的进程相比CPU消耗比较高的进程更容易找到,提供了交互和I/O消耗性负载的性能。
SCHED_FIFO :实时调度,即操作系统教材中描述的FCFS,先到先服务。需要明确指定。当一个任务就绪时,添加到就绪队列的尾部,当CPU空闲时,首先分配给就绪队列的头部的任务,直到运行任务完成(除非有若干特别的情况发生,如任务主动让出cpu、发生阻塞进入等待队列、更高优先级的任务出现(多核CPU场景))。一般策略代码简单,但平均等待时间比较长,一个任务可能保持CPU时间过长。
SCHED_RR :实时调度,基于时间片轮转,即操作系统教材中描述的Round robin。需要明确指定。类似FCFS,使用时间片,CPU运行了就绪队列头部的任务一个时间片的时长后,将此任务放到就绪队列的尾部,调度就绪队列头部的新任务就行运行,直到时间片结束,按此循环。其中新产生的任务被添加到就绪队列的尾部。一般这种调度策略平均等待时间比较长。
使用建议:
1、长时间运行的任务所在线程创建时,不能设置为SCHED_FIFO调度策略模式,否则会阻塞其他优先级比较低的周期性实时的短任务。(经验教训,OTA升级过程所在的线程所在线程错误地以SCHED_FIFO创建,每次升级时导致了各种奇怪的问题,如心跳检测线程没反应了,导致不停重启应用组件。同时表现CPU占用95%以上。)
系统中既有普通分时调度SCHED_OTHER,又有SCHED_FIFO或SCHED_RR调度策略时,进行了权重分配。如
Ubuntu18.04版本PC平台及linux 3.18.20 ARM平台测试,cd 到/proc/sys/kernel目录下操作
$ cat sched_rt_runtime_us
950000
$ cat sched_rt_period_us
1000000
表示实时任务运行周期是1秒,运行周期内最多允许0.95秒,剩余时间为普通进程的运行时间。
Linux为实时进程设置100个优先级:0~99,其中0为最高,99为最低
int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1));
内核源代码中注释如下:
Initialize thread attribute *ATTR with default attributes
(detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
no user-provided stack).
表示:使用默认参数初始化线程属性 ,可分离状态为 PTHREAD_JOINABLE,调度策略为SCHED_OTHER,不使用用户栈
int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
__THROW __nonnull ((1));
scheparam.__sched_priority = (优先级数值);
pthread_attr_setschedparam(&attr,&scheparam);
int pthread_attr_setinheritsched (pthread_attr_t *__attr,
int __inherit)
__THROW __nonnull ((1));
int pthread_attr_destroy (pthread_attr_t *__attr) __THROW __nonnull ((1));
如果pthread_attr_init中动态创建了内存空间,则这里会释放。
###1.5.1.使用函数
int pthread_getschedparam (pthread_t __target_thread,int *__restrict __policy,struct sched_param *__restrict __param) __THROW __nonnull ((2, 3));
###1.5.2.打印策略和优先级函数封装
void printCurrentThreadPriority()
{
struct sched_param sch;
int policy = -1;
pthread_t pt;
int res =-1;
pt = pthread_self();
res = pthread_getschedparam(pt , &policy, &sch) ;
if(res!=0)
{
printf("[Thread]pthread_getschedparam error,res=%d\n",res);
}
printf("[Thread]:pid=%d,ppid=%d,uid=%d,euid=%d,gid=%d,egid=%d ,threadid=0x%lx,priority=%d,policy=%d(0:OTHER,1:FIFO,2:RR)\n"
, getpid(),getppid(),getuid(),geteuid(),getgid(),getegid(),(unsigned long) pthread_self(),sch.sched_priority,policy);
}
###1.5.3.插入线程进行打印
进程的主线程main中进行打印:
[Thread]:pid=24416,ppid=1,uid=0,euid=0,gid=0,egid=0 ,threadid=0xb6eed000,priority=0,policy=0(0:OTHER,1:FIFO,2:RR)
通过pthread_create创建,但属性参数传递NULL创建的线程中打印:
[Thread]:pid=21790,ppid=1,uid=0,euid=0,gid=0,egid=0 ,threadid=0xb64ff450,priority=0,policy=0(0:OTHER,1:FIFO,2:RR)
通过pthread_create创建,但属性参数传递调度策略为SCHED_FIFO,优先级为65的线程中打印:
[Thread]:pid=24416,ppid=1,uid=0,euid=0,gid=0,egid=0 ,threadid=0xb6e7a450,priority=65,policy=1(0:OTHER,1:FIFO,2:RR)
备注:运行平台linux 3.18.20,arm单处理器
UNIX环境高级编程,第3版, [Advanced Programming in the UNIX Environment, Third Edition]
操作系统概念,第6版,西尔伯查茨著 郑扣根译 高等教育出版社
性能之巅,【美】格雷格(Brendan Gregg,B.) ,2015年8月 ,电子工业出版社
https://blog.csdn.net/u013007900/article/details/49965261/ https://blog.csdn.net/u012007928/article/details/40144089