300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > pthread调度策略 优先级和竞争范围

pthread调度策略 优先级和竞争范围

时间:2022-08-02 06:31:52

相关推荐

pthread调度策略 优先级和竞争范围

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

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

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

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

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

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

进程竞争范围比系统竞争范围“更好”,因为你不会阻止其他进程或内核中的某个线程运行SCHED_RR比SCHED_FIFO“更好”,并且具有可移植性,因为SCHED_RR线程将在具有相同优先级线程共享可用处理器时间间隔中被抢占对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.实现不允许应用程序将参数改动为特定的值

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

竞争范围和分配域

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 与当前进程中的其他线程竞争*/

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

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

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

相关优先级互斥量

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

#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_PROTECTint 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

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

优先级ceiling互斥量

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

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

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

优先级继承互斥量

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

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

核实体

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

处理机:物理硬件

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。