0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

英创信息技术Linux系统调度简介

英创信息技术 来源:英创信息技术 作者:英创信息技术 2020-02-05 10:31 次阅读

1、综述

Linux作为多任务、多用户的操作系统,其进程/线程调度管理是实现这些特性的关键部分。调度管理决定系统中的众多线程中哪个线程获得执行、什么时候开始执行、执行多久。一个好的调度算法能优化系统资源的使用,提高系统使用效率。

Linux内核中实现了Scheduler Classes,来实现多个调度类(Scheduler class)的协同工作,每个不同的调度类对应不同的类型的线程,而且每个调度类都有自身的优先级,Linux调度管理基础代码会遍历在内核中注册了的调度类,选择高优先级的调度类,然后让此调度类按照自己的调度算法选择下一个执行的线程。Linux系统中常用的几种调度类为SCHED_NORMAL、SCHED_FIFO、SCHED_RR。其中SCHED_NORMAL是用于普通线程的调度类,而SCHED_FIFO和SCHED_RR是用于实时线程的调度类,优先级高于SCHED_NORMAL。内核中区分普通线程与实时线程是根据线程的优先级,实时线程拥有实时优先级(real-time priority),默认取值为0~99,数值越高优先级越高,而普通线程只具有nice值,nice值映射到用户层的取值范围为-20~+19,数值越高优先级越低,默认初始值为0 ,子线程会继承父线程的优先级。对于实时线程,Linux系统会尽量使其调度延时在一个时间期限内,但是不能保证总是如此,不过正常情况下已经可以满足比较严格的时间要求了。下面将分别介绍这些调度类。

2、SCHED_NORMAL

对于SCHED_NORMAL,2.6之前的版本内核中的调度管理程序是根据线程的优先级(nice值)来分配一个固定的时间片(timeslice)给线程,比如nice值0对应于100ms的时间片,而nice值-20对应于5ms时间片,线程在执行过程中进入阻塞状态(I/O操作等引起)或者是执行的时间达到分配的时间片后将会被抢占,而新进入运行态的线程会根据其优先级和可用时间片来决定是否抢占当前正在执行的程序。

2.6之后版本的Linux中SCHED_NORMAL使用的是Linux 内核在2.6.23版本中引入的CFS(Complete Fair Scheduler)调度管理程序。CFS与之前的调度不同的是,线程的优先级与时间片之间并没有一个固定的关系,而是影响该线程在整个系统CPU运行时间中占有比例的一个因素。比如有两个线程,对应的nice值分别为0(普通线程)和+19(低优先级线程),那么普通线程将会占有19/20×100%的CPU时间,而低优先级线程将会占有1/20×100%的CPU时间(具体数值只做举例说明用,Linux内核中的计算出来的数值会不一样)。而如果同时运行的只有两个相同优先级的线程,那么他们分到的CPU时间各是50%。这样每个线程能够分配到的CPU时间占有比例跟系统当前的负载(所有处于运行态的线程数以及各线程的优先级)有关,同一个线程在他本身优先级不变的情况下分到的CPU时间占比会根据系统负载变化而发生变化,也即与时间片没有一个固定的对应关系。

理想情况下CFS对CPU时间占比的衡量是在一个无限小的时间片内计算单个线程执行时间的占比,CFS的目标是所有线程在这个小的时间片周期内执行的时间都是相同的,无限小在现实中显然是不存在的,Linux系统中这个时间片周期是与系统CPU数有关的,默认情况下单核CPU对应6ms,双核CPU对应12ms,8核CPU对应24ms,当线程数增加到很大数量时,CFS会保证每个线程获得最小执行时间, 单核CPU对应0.75ms,双核CPU对应1.5ms,8核CPU对应3ms。在CFS管理下,某个线程运行时如果进入阻塞态(或其他非运行态)或者当前时间片周期内的CPU时间占比达到后将会暂停运行,CFS然后将会选择当前时间片周期内已执行时间最少的运行态线程继续运行。当然CPU时间占比在内核中也是以运行时间衡量的,比如某个单核CPU系统中只有两个相同优先级的线程同时处于运行态,那么CFS将会以6ms为周期来调度所有线程,而每个6ms周期内每个线程分得3ms执行时间,如果某个线程中有I/O操作等其他操作使该线程进入非运行态,CFS将会立即使另外一个线程继续运行,如果两个线程都是基本没有I/O操作等会引起阻塞的操作(比如忙循环),那么线程将会在自己的执行时间结束(本质上是超出CPU时间占比)后被CFS程序调度出当前正在执行的状态,另外一个线程获得CPU资源开始执行。

需要注意的是,进入CFS(或其他调度算法)需要调度事件的产生,调度事件可以是线程自己调用函数显示执行调度,或者线程执行I/O操作等会进入阻塞的操作以及等待的事件发生线程进入运行态等(内核中有固定的调度点),如果一个程序一直处于忙计算(比如忙循环程序),那么就会需要系统软时间中断来产生调度事件从而进入CFS调度判断下一个可执行程序。目前我们的Linux内核普遍配置的系统软时间中断产生的频率为100Hz,也即每10ms产生一次中断,那么系统中只有忙计算类(如忙循环)线程的情况下,只有当系统产生软时间中断时,CFS才会被调用来判断下一个执行的线程并使其占有CPU开始执行,这个现象看起来就好象是Linux调度策略简单的给每个线程分配了10ms的时间片,其实并不是这样。如果系统中同时有忙计算类的线程和经常进行I/O操作类的线程,由于I/O类线程基本处于等待事件的阻塞态中,执行的时间很少,而计算类线程在执行的时间会比较长,如果计算类线程正在执行时,I/O类线程等待的事件发生了,CFS马上就会判断出I/O类线程在之前时间段内执行的时间很少,即已使用的CPU占比与分配给他的相比很小,而计算类线程很有可能已经超过了分配的CPU占比,那么CFS将会马上使I/O类的线程占有CPU开始执行,如此系统总是能及时响应I/O类线程。

3、SCHED_FIFO和SCHED_RR

SCHED_FIFO和SCHED_RR是实时线程使用的调度管理算法。SCHED_FIFO即先进先出,处于相同优先级的实时线程会根据进入运行态的次序依次执行。正在执行的线程会一直执行直到线程阻塞或者其主动调用调度线程放弃执行,处于此调度策略下的线程没有预先分配的时间片,可以永远执行下去。只有拥有更高实时优先级且处于SCHED_RR或者SCHED_FIFO管理下的线程能抢占正在运行的实时线程。

SCHED_RR在SCHED_FIFO的基础上会预先给定线程一个时间片,时间片达到后会使其他相同优先级的线程开始执行。SCHED_RR的时间片轮询机制只对同等实时优先级的线程有效,更高实时优先级的线程总是会抢占正在执行的线程,而低优先级的线程不能抢占高优先级的线程,即使其时间片已到。

实时线程优先级高于所有普通线程,如果有实时线程处于运行态,则系统调度时一定会选择调用实时线程;正在运行的实时线程只会被拥有更高实时优先级的线程抢占。所以在应用中如果需要将某个线程设置为实时线程,则需要用户自己确保该线程不会处于忙执行而完全占用CPU资源,导致其他普通线程没法获得CPU资源而一直被阻塞得不到执行,并且需要合理给予优先级的值,太高有可能会影响重要系统线程的运行。所有用户态线程默认没有实时优先级,都属于普通线程。

4、相关接口函数

Linux系统提供了一系列函数,这些函数可以让用户方便的修改线程/进程的优先级(包括nice值和real-time priority)、以及修改调度策略、设置运行线程的CPU核心等。下面简单介绍一下常用的函数。

(1)修改nice值

int nice ( int incr )

将调用进程的nice值增加incr,incr为负数是提高优先级,为正数时降低优先级。成功返回0。

int setpriority ( int which, id_t who, int prio )

将指定的线程/线程组/用户的nice值设置为prio,whice对应可以取值PRIO_PROCESS、PRIO_PGRP、PRIO_USER,who对应为线程/进程id,组id或者用户id,prio取值范围为-20~19。成功返回0,错误返回-1。

(2)修改real-time priority以及调度策略

int pthread_attr_setschedparam (pthread_attr_t *attr, const struct sched_param *param)

设置调度属性。对于SCHED_FIFO和SCHED_RR,sched_param值包含 int sched_priority,也即real-time priority。下面所有param定义相同。

int pthread_attr_getschedparam (const pthread_attr_t *attr, struct sched_param *param)

获取调度属性。

int pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy)

设置调度策略,policy可设置为SCHED_FIFO,SCHED_RR和SCHED_NORMAL。

int pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *policy)

获取调度策略。

int sched_setparam (pid_t pid, const struct sched_param *param)

设置pid进程的real-time priority,需要pid进程出具SCHED_FIFO或者SCHED_RR调度策略管理下。

int sched_getparam(pid_t pid, struct sched_param *param)

获取real-time priority。

int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param)

设置pid进程的调度策略以及调度属性。

int sched_getscheduler (pid_t pid)

返回pid进程调度策略。

(3)设置线程在哪个CPU核心上运行

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)

int sched_setaffinity (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)

int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *cpuset)

设置/获取线程可以运行的CPU核心, cpusetsize 可以设置为sizeof(cpu_set_t), cpuset可以用宏CPU_ZERO和CPU_SET设置,函数设置成功后,线程将只会在设置的CPU核心(比如8核CPU可以设置核心1、3、4)上运行,如果cpuset只指定了一个核心,那么线程将只会在此核心上运行。函数出错返回-1,成功返回0。

关于以上函数以及更多与调度相关的函数的详细信息请参考

http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html

http://pubs.opengroup.org/onlinepubs/7908799/xsh/sched.h.html

以及相关函数的Linux man手册和其他相关书籍资料

5、编程示例

下面提供一个示例程序,程序用于展示real-time priority对于进程运行时调度管理的影响,程序运行于ESM6802(双核)工控主板上。程序会在主进程中使用fork新建一个进程,然后调用sched_setscheduler设置子进程的实时优先级为30, 同时设置其使用SCHED_FIFO调度策略,而主进程只有nice值为0 的普通优先级。两个进程主体部分相同,均为在忙循环中置高然后置低一位GPIO的输出电平,通过示波器观察GPIO的状态,如果进程一直执行,则会看到连续的周期较固定的方波,而如果进程被其他进程抢占,则会看到GPIO的状态很长时间没有发生变化,以此来展示实时优先级对系统调度的影响。程序部分代码如下:

int gpio = GPIO6;

structsched_param rt_param = {

.sched_priority = 30 }; //实时优先级30

child_pid = fork(); //创建子进程

if(child_pid!=0) //child_pid不等于0为主进程,等于0为子进程

{

if( -1 == sched_setscheduler ( child_pid, SCHED_FIFO, &rt_param ) )

printf("sched_setscheduler failed\n");

//设置子进程实时优先级以及调度算法

printf ( "child_pid = %d\n", child_pid );

gpio = GPIO5; //主进程和子进程操作不同的GPIO

}

printf("Driver esm6800_gpio test\n");

fd = open("/dev/esm6800_gpio", O_RDWR);

printf("open file = %d\n", fd);

rc = GPIO_OutEnable(fd, 0xff); //set GPIO as output

if(rc < 0)

{

printf("GPIO_OutEnable::failed %d\n", rc);

returnrc;

}

for(;;) //无限循环

{

//忙循环中置高然后置低gpio输出电平

rc = GPIO_OutSet(fd, gpio); //使GPIO输出高电平

if(rc < 0)

{

printf("GPIO_OutSet::failed %d\n", rc);

returnrc;

}

rc = GPIO_OutClear(fd, gpio); //使GPIO输出低电平

if(rc < 0)

{

printf("GPIO_OutClear::failed %d\n", rc);

returnrc;

}

}

使用示波器查看到的GPIO状态如下图,其中黄色信号为主进程操作的GPIO5,蓝色信号为有实时优先级的子进程操作的GPIO6:

可以看出蓝色信号代表的拥有实时优先级的进程一直处于执行当中,没有被其他低优先级的进程抢占,而黄色信号代表的普通优先级的程序gpio状态切换有很明显的中断,也即其他进程被抢占而中断执行。此结果与第一节介绍的Linux调度策略一致:实时线程只会被拥有更高实时优先级的线程抢占,处于SCHED_FIFO下的实时线程可以无限执行。

用户在实际编程中应该仔细规划自己的程序,合理利用系统调度接口函数,来优化自己程序的执行效果,同时避免错误的使用导致系统正常运行。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11219

    浏览量

    208879
  • 嵌入式主板
    +关注

    关注

    7

    文章

    6085

    浏览量

    35198
收藏 人收藏

    评论

    相关推荐

    中科达荣获2024年软件和信息技术服务优秀企业

    及前百家企业”名单。中科达凭借非凡的技术实力与持续的创新能力,成功入选“2024年度软件和信息技术服务竞争力百强企业”以及“2024年软件和信息技术服务优秀企业”。
    的头像 发表于 10-30 11:44 372次阅读

    国产化背景下的工控主板发展现状

    ,是信息技术应用创新产业的简称,于2016年“信工委会”(信息技术应用创新工作委员会)提出,目的就是要推动我们国内软硬件关键技术的研发
    的头像 发表于 09-21 16:15 317次阅读

    加速鲲鹏落地!拓维信息迁移工具荣获鲲鹏原生开发技术认证

    认证。图/拓维·数据库适配中间件取得鲲鹏原生开发N认证在数字化时代的大潮中,信战略作为国家推动信息技术应用创新、保障信息安全与自主可控的关键举措,其重要性日益凸显
    的头像 发表于 09-10 08:03 386次阅读
    加速鲲鹏落地!拓维<b class='flag-5'>信息</b>信<b class='flag-5'>创</b>迁移工具荣获鲲鹏原生开发<b class='flag-5'>技术</b>认证

    梯度科技入选2023年信息技术应用创新解决方案名单

    日前,工业和信息化部网络安全产业发展中心(工业和信息化部信息中心)在天津举办2024信息技术应用创新发展大会暨解决方案应用推广大会。会上正式公布了2023年
    的头像 发表于 09-09 16:29 384次阅读

    中软国际信服务助力大连信产业发展

    为进一步激发大连本地信产业生态的活力与潜力,搭建一个高效、开放的交流平台。由大连软件行业协会携手大连市信息技术应用创新综合服务中心主办,中软国际协办的,2024年大连市信息技术应用创新产业发展大会
    的头像 发表于 08-27 16:49 800次阅读

    深入探讨Linux的进程调度

    Linux操作系统作为一个开源且广泛应用的操作系统,其内核设计包含了许多核心功能,而进程调度器(Scheduler)就是其中一个至关重要的模块。进程
    的头像 发表于 08-13 13:36 890次阅读
    深入探讨<b class='flag-5'>Linux</b>的进程<b class='flag-5'>调度</b>器

    车辆调度系统

    【铭迹创新】车辆调度系统分为隧道内和隧道外,隧道内应用UWB精确定位、RFID等技术,对隧道内施工车辆进行定位及区分行车道,综合应用红绿灯,LED屏幕、广播等技术对隧道内车辆进行有效的
    的头像 发表于 05-31 15:59 424次阅读
    车辆<b class='flag-5'>调度</b><b class='flag-5'>系统</b>

    翼辉信息入选2023年信息技术应用创新解决方案名单

    近日,2023 年(第五届)信息技术应用创新解决方案公布遴选名单,历经资格初审、技术中评、区域评议、终评预审,翼辉以“面向工业领域嵌入式操作系统 SylixOS 解决方案”,成功在全国优秀方案中脱颖而出,入选典型解决方案名单。
    的头像 发表于 04-28 11:37 522次阅读
    翼辉<b class='flag-5'>信息</b>入选2023年<b class='flag-5'>信息技术</b>应用创新解决方案名单

    芯盾时代中标西安西热电站信息技术有限公司!

    芯盾时代中标西安西热电站信息技术有限公司!芯盾时代基于完整的身份安全产品体系,增强客户的业务系统、网络设备和安全设备等认证安全强度
    的头像 发表于 04-09 11:32 465次阅读

    基于物联网、大数据、云计算等现代信息技术高速公路智慧消防平台解决方案

    安科瑞 程瑜 系统简介 1、概述 智慧消防云平台基于物联网、大数据、云计算等现代信息技术,将分散的火灾自动报警设备、电气火灾监控设备、智慧烟感探测器、智慧消防用水等设备连接形成网络,并对这些设备
    的头像 发表于 03-15 14:20 405次阅读
    基于物联网、大数据、云计算等现代<b class='flag-5'>信息技术</b>高速公路智慧消防平台解决方案

    龙芯中科三项信方案入围工信部2023年信息技术应用创新应用示范案例名单

    近日,工业和信息化部通报了2023年信息技术应用创新解决方案征集遴选结果,本次共评选出典型解决方案173个、应用示范案例83个、单项创新案例64个。
    的头像 发表于 03-07 16:45 854次阅读
    龙芯中科三项信<b class='flag-5'>创</b>方案入围工信部2023年<b class='flag-5'>信息技术</b>应用创新应用示范案例名单

    RX78M组 EtherCAT ETG.5003示例程序固件信息技术

    电子发烧友网站提供《RX78M组 EtherCAT ETG.5003示例程序固件信息技术.pdf》资料免费下载
    发表于 02-21 14:22 1次下载
    RX78M组  EtherCAT ETG.5003示例程序固件<b class='flag-5'>信息技术</b>

    软通动力与捷技术签订战略合作协议

    近日,软通动力信息技术(集团)股份有限公司(以下简称“软通动力”)与宁波捷技术股份有限公司(以下简称“捷技术”)正式签订战略合作协议,并
    的头像 发表于 02-03 16:35 1081次阅读

    PCB企业力三期项目顺利投产

    近日,PCB企业四川力电子科技股份有限公司三期(载板厂和特种板厂)顺利投产。通过这个项目,力公司成功地将业务范围从单一的普通通孔多层板扩展到了高端的IC载板、MiniLED基板
    的头像 发表于 01-15 14:20 567次阅读

    兆芯正引入Linux首选内核调度技术,优化性能

    近期,兆芯工程团队亦在致力于将首选内核调度技术引进Linux系统中。他们试图通过提议的Linux内核补丁,利用已有的ACPI功能来辨别每个核
    的头像 发表于 12-29 14:30 523次阅读
    兆芯正引入<b class='flag-5'>Linux</b>首选内核<b class='flag-5'>调度</b><b class='flag-5'>技术</b>,优化性能