实时调度:操作系统在有限的时间内提供特定水平的服务能力。受限制的响应时间不一定是块的反应,意味着可预知的响应速度。如果系统定义_POSIX_THRAED_PRIORITY_SCHEDULING,它为线程指派实时调度优先级提供支持。支持_POSIX_THRAED_PRIORITY_SCHEDULING的系统必须提供至少包括成员seched_priority的struct  sched_param结构体的定义,seched_priority的标准策略是SCHED_FIFO和SCHED_RR使用的唯一参数。

  影响实时调度:调度策略,参数,竞争范围和分配域

  实时调度在某种程度上不一定很快,实时调度可能会变得很慢,因为它包含了更多抢占检查的开销特别是在一台多处理机上

  固定优先级调度可能会导致优先级倒置,优先级倒置——低优先级线程阻塞高优先级线程运行,他是调度和同步之间一个不干净的相互作用的结果。调用要求一个线程运行,但是同步要求运用另行的线程,所以两个优先级好像颠倒。如:一个低优先级线程获互斥资源,并且被一个随后在同样资源阻塞的高优先级线程抢占时,优先级发生倒置,在只有两个线程被允许运行时,低优先级线程被先执行,然后释放互斥量,如果在他们之间有第三个线程准备好时,他能阻塞低优先级线程运行,因为低优先级线程拥有高优先级线程拥有的互斥量,中间优先级线程阻止了高优先级线程的执行

  优先级调度不完全可移植。如:使用系统竞争范围时,你的线程可以直接与操作系统内核线程相竞争,提高自定义线程的优先级可能会阻止内核I/O驱动在系统上的一些工作

  确实需要使用优先级调度时(一般避免使用,因为相比解决问题,他会引起更多的问题),应记住:

  1. 进程竞争范围比系统竞争范围“更好”,因为你不会阻止其他进程或内核中的某个线程运行
  2. SCHED_RR比SCHED_FIFO“更好”,并且具有可移植性,因为SCHED_RR线程将在具有相同优先级线程共享可用处理器时间间隔中被抢占
  3. 对SCHED_FIFO和SCHED_RR而言,低优先级比高优先级更好,因为能更少的妨碍另外重要的东西
//1.设置的最高和最低优先级,policy: 可以取三个值(SCHED_FIFO、SCHED_RR、SCHED_OTHER)
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);//2.设置和获取优先级
//param是struct sched_param类型的指针,它仅仅包含一个成员变sched_priority,指明所要设置的静态线程优先级。
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
param.sched_priority = 51; //设置优先级
struct sched_param
{int __sched_priority; // 所要设定的线程优先级
};//3.改变策略(静态改变策略和设置优先级)
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int policy);//4.继承调度属性,该属性控制了你创建的线程从创建线程那继承调度信息,schedpolicy和schedparam显示设置调度信息
//我手动设置了调度策略或优先级时,必须显示的设置线程调度策略的inheritsched属性,因为pthread没有为inheritsched设置默认值
//所以在改变了调度策略或优先级时必须总是设置该属性。
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
/*
第一个函数中inheritsched的取值为:PTHREAD_INHERIT_SCHED 或者 PTHREAD_EXPLICIT_SCHED。
前者为继承创建线程的调度策略和优先级,后者指定不继承调度策略和优先级,而是使用自己设置的调度策略和优先级。
无论何时,当你需要控制一个线程的调度策略或优先级时,必须将inheritsched属性设置为PTHREAD_EXPLICIT_SCHED。
*///5.置正在运行的线程的调度策略和优先级(动态设置线程的调度策略和优先级)
//前面的那些函数只能通过线程的属性对象 pthread_attr_t 来设置线程的调度策略和优先级,不能够直接设置正在运行的线程的调度策略和优先级
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);
//在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_setschedparam() 函数将失败并返回
//相应的值--EINVAL所设置属性的值无效。ENOTSUP--尝试将该属性设置为不受支持的值。
//int pthread_setschedparam:thread参数所指向的线程不存在
//int pthread_getschedparam:1.参数policy或同参数policy关联的调度参数之一无效;//2.数policy或调度参数之一的值不被支持;//3.调用线程没有适当的权限来设置指定线程的调度参数或策略//4.参数thread指向的线程不存在;5.实现不允许应用程序将参数改动为特定的值

  1. SCHED_OTHER(是Linux默认的分时调度策略):它是默认的线程分时调度策略,所有的线程的优先级别都是0(不使用sched_param结构体的sched_priority成员),如果系统使用这种调度策略,程序将无法设置线程的优先级。这种调度策略也是抢占式的,当高优先级的线程准备运行的时候,当前线程将被抢占并进入等待队列。这种调度策略仅仅决定线程在可运行线程队列中的具有相同优先级的线程的运行次序。(使用此方式的代码不可移植)
  2. SCHED_FIFO:它是一种实时的先进先出调用策略,且只能在超级用户下运行。这种调用策略仅仅被使用于优先级大于0的线程。使用SCHED_FIFO的线程运行到有更高级的线程准备好或者愿意自己阻塞为止;当有一个线程准备好时,除非有平等或更高级的线程准备好,否则他将很快运行自己。如果有若干相同优先级的线程等待执行,然而最早执行的线程无终止或者阻塞动作,那么其他线程是无法执行的,除非当前线程调用如pthread_yield之类的函数,所以在使用SCHED_FIFO的时候要小心处理相同级别线程的动作。
  3. SCHED_RR:若有一个此类的线程运行超过一定的时间没有阻塞,而另外的SCHED_RR或SCHED_FIFO策略相同优先级的线程准备好时,运行的线程将被枪占意识准备好的线程运行。
  4. 对于 SCHED_OTHER 策略,sched_priority 只能为 0。对于 SCHED_FIFO,SCHED_RR 策略,sched_priority 从 1 到 99。
  5. 调度策略和优先级是分开来描述的。前者使用预定义的SCHED_RR、SCHED_FIFO、SCHED_OTHER,后者是通过结果体struct sched_param给出的。
  6. 这些设置调度策略和优先级的函数操作的对象是线程的属性pthread_attr_t,而不是直接来操作线程的调度策略和优先级的。函数的第一个参数都是pthread_attr_t。
  7. 当pthread_setschedparam函数的参数 policy == SCHED_RR 或者 SCHED_FIFO 时,程序必须要在超级用户下运行
  8. pthread_setschedparam 函数改变在运行线程的调度策略和优先级肯定就不用调用函数来设置inheritsched属性了:pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED); 因为该函数设置的对象是pthread_attr_t 
  9. 当在对象属性中设置调度策略或优先级时,必须同时设置inheritsched属性
  10. 改变线程属性中调度策略和参数时是两个操作,修改调度策略和修改参数
  11. 不能独立于线程的参数来修改一个可执行线程的调度策略,为了调度正确操作,参略和参数一定是一致的,每个调度策略有一个优先级的唯一范围,并且一个线程不能对一个对当前调度策略而言无效的优先级执行。

竞争范围和分配域

int pthread_attr_getscope(pthread_attr_t *attr, int *scope);/*返回值:若是成功返回0,否则返回错误的编号形  参:attr       指向一个线程属性的指针scope      返回线程的作用域*/
//指定了线程与谁竞争资源
int pthread_attr_setscope(pthread_attr_t *attr, int scope);/*返回值:若是成功返回0,否则返回错误的编号attr       指向一个线程属性的指针guardsize  线程的作用域,可以取如下值PTHREAD_SCOPE_SYSTEM    与系统中所有进程中线程竞争PTHREAD_SCOPE_PROCESS   与当前进程中的其他线程竞争*/

  竞争范围:描述了线程为处理资源而竞争的方式,系统竞争范围意味着线程与进程之外的线程竞争处理器资源,一个进程内的高优先级系统竞争范围线程能阻止其他进程内的系统竞争范围运行。竞争范围指的是仅仅在同一进程内相互竞争。

  分配域:系统内线程可以为其他竞争的处理器的集合。一个系统可以有一个以上的分配域,每个包含一个以上的处理器,在一个单处理器的处理机上,各个分配域可以包含从一个处理器到系统中所有的处理器。(没有实现该接口)

  1. 竞争范围内的线程可以共享一个核实体
  2. 系统竞争范围线程之间的环境切换通常要求至少一次内核调用
  3. 竞争范围在优先级调度上没有给你真正的控制——高优先级的线程可以优先于进程内的其他线程运行
  4. 当一个线程被分配超过一个处理机的分配域时,应用程序不能完全依靠可预知的调度行为;如:高优先级和低优先级可以同时运行,调度程序不允许因为一个高优先级的线程正在运行而是处理及闲置,单处理机行为在一台多处理机上没什么意思。

相关优先级互斥量

  不仅避免实时调度可以避免优先级倒置,而且用互斥量加锁协议也可以避免优先级倒置

#if defined (_POSIX_THREAD_PRIO_PROSTECT) \||defined (_POSIX_THREAD_PRIO_INHERIT)
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,int *protocol);
int pthread_mutexattr_setprotocol(const pthread_mutexattr_t *attr,int protocol);
#endif#if defined _POSIX_THREAD_PRIO_PROTECT
int pthread_mutexattr_getprioceiling(const pthread_attr_t *attr,int *prioceiling);
int pthread_mutexattr_setprioceiling(const pthread_attr_t *attr,int prioceiling); int pthread_mutex_getprioceiling(const pthread_attr_t *attr,int *prioceiling);
int pthread_mutex_getprioceiling(const pthread_attr_t *attr,int prioceiling);
#endif

  1. 加锁或等待这些属性之一的某个互斥量可以改变线程的优先级——或另外优先级的到来,来保证互斥量的线程不能被需要锁住相同互斥量的其他线程抢占。
  2. _POSIX_THREAD_PRIO_PROSTECT和_POSIX_THREAD_PRIO_INHERIT这些宏定义在<unistd.h>中,对应用进行条件编译,活用sysconf来检查。
  3. 一旦创建了使用这些属性之一的互斥量,就能对任何其他互斥量一样来枷锁和解锁互斥量,使用pthread_mutex_init就能变换创建的互斥量
  4. 如果定义_POSIX_THREAD_PRIO_PROSTECT,则它支持“优先级ceiling协议”和prioceiling属性,通过调用pthread_mutexattr_setprotocol设置协议属性,如果将协议属性设置为_POSIX_THREAD_PRIO_PROSTECT,则可以通过设置prioceiling属性使用属性对象创建互斥量优先级设置ceiling。
  5. 调用pthread_mutexattr_setprioceiling设置prioceiling属性,当任何线程锁住与该属性对象相关定义的一个互斥量时,线程的优先级将被设置为互斥量的优先级ceiling,除非线程的优先级已经是相同或更高,在高于互斥量优先级ceiling的线程内加锁该互斥量会被打破协议,失去对优先级倒置的保护
  6. 优先级继承:当一个线程再由另个低优先级线程拥有的互斥量上等待时,后者优先级将被增加到等待线程的优先级。
  7. 如果定义_POSIX_THREAD_PRIO_INHERIT他就支持协议属性,如果将属性设置为_POSIX_THREAD_PRIO_INHERIT,那么保持互斥量的线程就不能被另外的与等待互斥量的线程相比优先级低的任何线程抢占,当任何线程加锁互斥量,同时一个低优先级的线程拥有互斥量时,只要它拥有互斥量,当前拥有互斥量的线程的优先级将被提高到等待线程的优先级

优先级ceiling互斥量

  当使用优先级ceiling创建一个互斥量时,指定的线程锁住互斥量时可以拥有最高的优先级,任何锁住互斥量的线程将自动将它的优先级值提高到那个值,这允许在他被任何另外试图加锁该互斥量的线程抢占以前,完成对互斥量的操作。

  一个优先级ceiling互斥量在一个库函数中无法使用。

  如果有任何比ceiling高的优先级运行的线程锁住优先级ceiling互斥量,协议将被破坏。

优先级继承互斥量

  当一个线程锁住互斥量时,线程的优先级就被互斥量控制,当另外的线程在那个互斥量上阻塞时,他会查看拥有互斥量的线程优先级,如果拥有互斥量的线程比试图在互斥量上阻塞的线程优先级低,则拥有互斥量的线程的优先级将被提升到阻塞线程的优先级。

  除非等待的线程也被抢占,提高优先级确保拥有互斥量的线程不能被抢占;拥有互斥量的线程代表的是高优先级工作的线程,当线程互斥量解锁时,线程的优先级被自动降到他原来的优先级,高优先级等待线程将被唤醒,如果又有一个高优先级线程在互斥量上阻塞,拥有互斥量的线程将再次增加优先级。

核实体

  线程:调用pthread_create创建的一个线程,类行为pthread_t的一个标识符代表,使用pthreads接口可控制

  处理机:物理硬件

  核实体:线程和处理机间的一层附加抽象,可能是一个传统的UNIX进程。

  线程与核实体的交互方式:多对一(用户级),一对一(内核级),多对少

转载于:https://www.cnblogs.com/tianzeng/p/9192706.html

pthread调度策略,优先级和竞争范围相关推荐

  1. oracle的PRIPID字段,【学习笔记】Oracle进程调度策略优先级 high_priority_processes案例...

    [学习笔记]Oracle进程调度策略优先级 high_priority_processes案例 时间:2016-10-27 21:51   来源:Oracle研究中心   作者:HTZ   点击: 次 ...

  2. 【C++ 语言】线程 ( 线程创建方法 | 线程标识符 | 线程属性 | 线程属性初始化 | 线程属性销毁 | 分离线程 | 线程调度策略 | 线程优先级 | 线程等待 )

    文章目录 I 线程创建方法 II 线程执行函数 III 线程标识符 IV 线程属性 V 线程属性 1 ( 分离线程 | 非分离线程 ) VI 线程属性 2 ( 线程调度策略 ) VII 线程属性 3 ...

  3. 优先级反转和优先级继承

    iOS的锁中有一个自选锁OSSpinLock , 这个api被标记为不推荐 , 理由就是会产生优先级反转的问题, 当时并不是特别理解这个优先级反转 . 后来在看一本书 <算法之美> 里在讲 ...

  4. Java 从多线程到并发编程(五)—— 线程调度 优先级倒置(反转) 阻塞 死锁 suspend

    文章目录 前言 ´・ᴗ・` 线程调度策略 优先级倒置问题 优先级倒置解决方案 死锁 dead lock suspend 被阻塞的同时持有资源不放 是上述问题的诱因 总结 ´◡` 前言 ´・ᴗ・` 这一 ...

  5. Linux 编程之进程篇:调度、优先级、亲和性和资源限制

    上篇文章介绍了 Linux 进程的数据结构和创建.退出. 这篇文章我们来看下处理器在调度不同进程时有什么策略,我们开发者可以如何影响处理器的调度. 文章目录 什么是调度 进程的调度 调度策略 获取调度 ...

  6. 浅析Linux线程调度

    在Linux中,线程是由进程来实现,线程就是轻量级进程( lightweight process ),因此在Linux中,线程的调度是按照进程的调度方式来进行调度的,也就是说线程是调度单元.Linux ...

  7. MSP432P401R TI Drivers 库函数学习笔记(二)认识TI-RTOS (TI-POSIX)

    目录 简介 TI-RTOS FreeRTOS POSIX 运行时对象查看器 (Runtime Object Viewer) TI-POSIX 介绍 在源代码中使用 POSIX TI-POSIX支持的函 ...

  8. Linux操作系统原理与应用03:进程

    目录 1. 进程简介 1.1 程序和进程 1.2 进程的定义 1.2.1 正文段 1.2.2 用户数据段 1.2.3 系统数据段 1.3 进程的层次结构 1.3.1 进程的亲缘关系 1.3.2 进程树 ...

  9. 安卓桌面软件测试自学,最全的安卓APP专项测试方法!不看悔青肠

    本文来自牛鹭学院学员:丁孟辉 App启动时间 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动 启动app命令:adb shell am ...

最新文章

  1. 我们的解决方案:日志系统
  2. 再见,卷积神经网络!
  3. AI人脸识别 生物识别 活体检测 的发展历程
  4. graduation wishes from professor Youmin Xi
  5. docker php 多端口,docker使用之php-fpm+apache多容器的xdebug和phpstorm的配置
  6. 【免费活动】字节跳动背后的音视频技术揭秘
  7. 面向对象——概念(成员变量、静态变量、成员方法、静态方法、垃圾回收机制、重载、包)...
  8. EF通用数据层封装类(支持读写分离,一主多从)
  9. mysql server 5.0安装教程_MySQL Server 5.0安装教程
  10. 论文浅尝 | Distant Supervision for Relation Extraction
  11. 语言学博士、Kaggle数据分析师,她说:读研不是必选项,这4项技能学校不教
  12. 梆梆加固还原DEX文件
  13. SharePoint快速调试技巧
  14. ovf导入虚拟服务器,云主机 导入 ovf
  15. Fluent Mybatis 牛逼!
  16. xp 开机画面【欢迎使用】四个字更改方法
  17. 关注我的微信公众帐号小q机器人(xiaoqrobot)
  18. 留住幸福的办法是不断创造幸福
  19. 三星被指盗取FinFET芯片专利技术 将被起诉
  20. Hadoop2.7.3 mapreduce(三)SequenceFile和MapFile 简介与应用

热门文章

  1. Linux服务器运行sh文件提示权限不够解决方法?飞腾服务器Permission denied问题授权方法
  2. 一个简单的因数分解java代码
  3. 使用 MWC V2.5 中的 MPU6050中的DMP进行计算姿态(转载)
  4. 8个独立按键控制LED
  5. [YTU]_2866(结构体---点坐标结构体)
  6. 9.1 图像处理的基本概念(图像读入、图像信息查询、图像显示和图像存储)
  7. 1.3.3 激活函数介绍
  8. ML---Simple Linear Regression
  9. linux 的功能,Linux的主要功能
  10. mysql5.6.28安装教程百度经验_Linux(Ubuntu)下Mysql5.6.28安装配置方法图文教程