疑问

两个线程分别有不同的调度策略,一个SCHED_FIFO,一个SCHED_OTHER,按照之前的理解,SCHED_FIFO实时线程一定会占用CPU一直运行,导致SCHED_OTHER的普通线程得不到CPU,事实是这样么?

验证

写了一小段代码,一个是验证SCHED_FIFO的高优先级线程会不会抢占低优先级的线程,在不主动放弃的情况下一直运行,一个是测试普通优先级的线程会不会得到CPU时间;

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define __USE_GNU
#include <pthread.h>
#include <sched.h> long long a = ;
long long b = ; int attach_cpu(int cpu_index)
{
int cpu_num = sysconf(_SC_NPROCESSORS_CONF);
if (cpu_index < || cpu_index >= cpu_num)
{
printf("cpu index ERROR!\n");
return -;
} cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(cpu_index, &mask); if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < )
{
printf("set affinity np ERROR!\n");
return -;
} return ;
} void *thread1(void *param)
{
attach_cpu(); long long i;
for (i = ; i < ; i++)
{
a++;
}
} void *thread2(void *param)
{
attach_cpu(); long long i;
for (i = ; i < ; i++)
{
b++;
}
} int main()
{
pthread_t t1;
pthread_t t2; int policy;
struct sched_param param; if (pthread_create(&t1, NULL, thread1, NULL) < )
{
printf("create t1 failed!\n");
return -;
} param.sched_priority = ;
policy = SCHED_FIFO;
pthread_setschedparam(t1, policy, &param); if (pthread_create(&t2, NULL, thread2, NULL) < )
{
printf("create t2 failed!\n");
return -;
} param.sched_priority = ;
policy = SCHED_FIFO;
pthread_setschedparam(t2, policy, &param); while ()
{
printf("a=%lld, b=%lld\n", a, b);
sleep();
} pthread_join(t1, NULL);
pthread_join(t2, NULL); return ;
}

通过运行结果来看:

1. SCHED_FIFO的高优先级线程会抢占低优先级线程;

2.SCHED_FIFO的高优先级线程一旦占用CPU并不主动放弃CPU的情况下将一直占用,此时低优先级线程得不到CPU时间;

3.主线程为SCHED_OTHER普通线程,得到了CPU时间,能够打印出信息;

原理

对于上述现象在manpage中已经有了很好的描述,以下摘录一些;前面的疑问在下面的限制实时线程的CPU使用时间部分;

调度策略

系统中的每个线程都关联了一个调度策略和优先级,调度器正是根据调度策略和优先级进行线程调度的,从而决定哪个线程将在下一个调度中得到CPU时间;

对于普通调度策略(SCHED_OTHER, SCHED_IDLE, SCHED_BATCH),优先级是没有作用的,实际上必须是0,这样实时测量线程可以马上抢占普通线程;

对于实时调度策略(SCHED_FIFO, SCHED_RR),优先级需要设置为1(最小)-99(最大)中的某个值;

调度器为每个优先级维护了一个待调度线程的列表,当需要进行调度时,调度器访问最高优先级的非空的列表,然后从列表头选择一个线程调度运行;

线程的调度策略决定了一个可调度线程应该放在哪个列表的哪个位置;

所有的调度都是支持抢占的,如果有高优先级的线程准备好运行了,那么它将抢占当前运行的线程,这使得当前线程被重新加入到等待调度的链表中;调度策略决定了在同一个优先级列表中的可调度线程的顺序;

SCHED_FIFO:先进先出调度

SCHED_FIFO线程的优先级必须大于0,当它运行时,一定会抢占正在运行的普通策略的线程(SCHED_OTHER, SCHED_IDLE, SCHED_BATCH);SCHED_FIFO策略是没有时间片的算法,需要遵循以下规则:

1)如果一个SCHED_FIFO线程被高优先级线程抢占了,那么它将会被添加到该优先级等待列表的首部,以便当所有高优先级的线程阻塞的时候得到继续运行;

2)当一个阻塞的SCHED_FIFO线程变为可运行时,它将被加入到同优先级列表的尾部;

3)如果通过系统调用改变线程的优先级,则根据不同情况有不同的处理方式:

a)如果优先级提高了,那么线程会被添加到所对应新优先级的尾部,因此,这个线程有可能会抢占当前运行的同优先级的线程;

b)如果优先级没变,那么线程在列表中的位置不变;

c)如果优先级降低了,那么它将被加入到新优先级列表的首部;

根据POSIX.1-2008规定,除了使用pthread_setschedprio(3)以外,通过使用其他方式改变策略或者优先级会使得线程加入到对应优先级列表的尾部;

4)如果线程调用了sched_yield(2),那么它将被加入到列表的尾部;

SCHED_FIFO会一直运行,直到它被IO请求阻塞,或者被更高优先级的线程抢占,亦或者调用了sched_yield();

SCHED_RR:轮转调度

SCHED_RR是SCHED_FIFO的简单增强,除了对于线程占用的时间总量之外,对于SCHED_FIFO适用的规则对于SCHED_RR同样适用;如果SCHED_RR线程的运行时间大于等于时间总量,那么它将被加入到对应优先级列表的尾部;如果SCHED_RR线程被抢占了,当它继续运行时它只运行剩余的时间量;时间总量可以通过sched_rr_get_interval()函数获取;

SCHED_OTHER:默认Linux时间共享调度

SCHED_OTHER只能用于优先级为0的线程,SCHED_OTHER策略是所有不需要实时调度线程的统一标准策略;调度器通过动态优先级来决定调用哪个SCHED_OTHER线程,动态优先级是基于nice值的,nice值随着等待运行但是未被调度执行的时间总量的增长而增加;这样的机制保证了所有SCHED_OTHER线程调度的公平性;

限制实时线程的CPU使用时间

SCHED_FIFO, SCHED_RR的线程如果内部是一个非阻塞的死循环,那么它将一直占用CPU,使得其它线程没有机会运行;

在2.6.25以后出现了限制实时线程运行时间的新方式,可以使用RLIMIT_RTTIME来限制实时线程的CPU占用时间;Linux也提供了两个proc文件,用于控制为非实时线程运行预留CPU时间;

/proc/sys/kernel/sched_rt_period_us

这个文件中的数值指定了总CPU(100%)时间的宽度值,默认值是1,000,000;

/proc/sys/kernel/sched_rt_runtime_us

这个文件中的数值指定了实时线程可以运行的CPU时间宽度,如果设置为-1,则认为不给非实时线程预留任何运行时间,默认值是950,000,因为第一个文件的总量是1,000,000,也就是说默认配置为非实时线程预留了5%的CPU时间;

manpage连接:http://man7.org/linux/man-pages/man7/sched.7.html

SCHED_FIFO与SCHED_OTHER调度机制的更多相关文章

  1. (笔记)Linux内核学习(十一)之I/O层和I/O调度机制

    一 块I/O基本概念 字符设备:按照字符流的方式被有序访问的设备.如串口.键盘等. 块设备:系统中不能随机(不需要按顺序)访问固定大小的数据片(chunk 块)的设备. 如:硬盘.软盘.CD-ROM驱 ...

  2. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  3. 定时组件quartz系列<三>quartz调度机制调研及源码分析

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  4. (1)quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析 原文地址:http://demo.netfoucs.com/gklifg/article/details/27090179 引言quartz集群架构调 ...

  5. quartz群调查调度机制和源代码分析

    pageId=85056282#quartz集群调度机制调研及源代码分析-quartz2.2.1集群调度机制调研及源代码分析" style="color:rgb(59,115,17 ...

  6. Linux进程组调度机制分析【转】

    转自:http://oenhan.com/task-group-sched 又碰到一个神奇的进程调度问题,在系统重启过程中,发现系统挂住了,过了30s后才重新复位,真正系统复位的原因是硬件看门狗重启的 ...

  7. [k8s]k8s的控制层kubelet+docker配合调度机制(k8架构)

    意外停掉一台node的kubelet,发现调度有问题,研究了下调度的细节 k8s架构 控制层- kubelet(配合节点docker工作) 数据层- kube-proxy 逻辑图: object 参考 ...

  8. Golang 的 协程调度机制 与 GOMAXPROCS 性能调优

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  9. [转]golang的goroutine调度机制

    golang的goroutine调度机制 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 一直对goroutine的调度机制很好奇最近在看雨痕的golang源码分析基于go ...

随机推荐

  1. elementui限制开始日期和结束日期

    项目需求:开始日期和结束日期 禁用当前日期之前的日期.同时结束日期 禁用开始日期之前的日期 <div class='startTime'> 开始时间:<el-date-picker ...

  2. 动画 jquery-transit

    <script type="text/javascript" src="js/jquery.min.js"></script> < ...

  3. H5之拖拽

    步骤: 1.为将要拖拽的元素设置允许拖拽,并赋予dragstart事件将其id转换成数据保存: 2.为容器添加dragover属性添加事件阻止浏览器默认事件,允许元素放置,并赋予drop事件进行元素的 ...

  4. node.js 调用mysql 数据库

    1.在package.json中添加mysql依赖 命令:npm install mysql --save 2.项目中添加mysql文件夹 > 文件夹下创建config文件夹,并在config下 ...

  5. 一个 Git 分支协作模式的进化故事

    从不用版本管理到使用 Git 分支管理的故事,也就是从这个时候开始的... 某公司只有一个程序员,一开始并没有版本管理的概念.项目开发只有一个人在参与,所以也没用版本管理工具. 后来,老板又招了两个程 ...

  6. sql的时间格式

    sql中的时间格式转换主要有:date_format函数,str_to_date函数 1. 首先选择一个数据库 use db_name; 2. 显示当前时区的时间: SELECT NOW(); 3. ...

  7. 跨域访问支持(Spring Boot、Nginx、浏览器)

    原文:http://www.itmuch.com/work/cors/ 最近家中事多,好久没有写点啥了.一时间竟然不知从何说起.先说下最近家里发生的事情吧: 老爸肺气肿住院: 老妈甲状腺囊肿 儿子喘息 ...

  8. ElasticSearch 连载一 基础入门

    ElasticSearch简写ES,ES是一个高扩展.开源的全文检索和分析引擎,它可以准实时地快速存储.搜索.分析海量的数据. 应用场景 我们常见的商城商品的搜索 日志分析系统(ELK) 基于大量数据 ...

  9. 大数据之路week07--day03(Hadoop深入理解,JAVA代码编写WordCount程序,以及扩展升级)

    什么是MapReduce 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃. MapReduce方法则是: 1.给在座的所有玩家中分配这摞牌 2.让每个玩家数自己手中的牌有几 ...

  10. 一个s的力量——http与https

    我们网络上有很多资源,那么我们怎么来访问呢?就拿一个小例子来说,我们都会用百度来搜索东西,就会在地址栏中输入这样的地址http://www.baidu.com这种访问方式就是通过URL来实现的,那么什 ...