【转】 pthread设置线程的调度策略和优先级
转自:https://www.cnblogs.com/tianzeng/p/9192706.html
线程的调度有三种策略:SCHED_OTHER、SCHED_RR和SCHED_FIFO。Policy用于指明使用哪种策略。下面我们简单的说明一下这三种调度策略。
SCHED_OTHER(是Linux默认的分时调度策略)
它是默认的线程分时调度策略,所有的线程的优先级别都是0,线程的调度是通过分时来完成的。简单地说,如果系统使用这种调度策略,程序将无法设置线程的优先级。请注意,这种调度策略也是抢占式的,当高优先级的线程准备运行的时候,当前线程将被抢占并进入等待队列。这种调度策略仅仅决定线程在可运行线程队列中的具有相同优先级的线程的运行次序。
SCHED_FIFO
它是一种实时的先进先出调用策略,且只能在超级用户下运行。这种调用策略仅仅被使用于优先级大于0的线程。它意味着,使用SCHED_FIFO的可运行线程将一直抢占使用SCHED_OTHER的运行线程J。此外SCHED_FIFO是一个非分时的简单调度策略,当一个线程变成可运行状态,它将被追加到对应优先级队列的尾部((POSIX 1003.1)。当所有高优先级的线程终止或者阻塞时,它将被运行。对于相同优先级别的线程,按照简单的先进先运行的规则运行。我们考虑一种很坏的情况,如果有若干相同优先级的线程等待执行,然而最早执行的线程无终止或者阻塞动作,那么其他线程是无法执行的,除非当前线程调用如pthread_yield之类的函数,所以在使用SCHED_FIFO的时候要小心处理相同级别线程的动作。
SCHED_RR
鉴于SCHED_FIFO调度策略的一些缺点,SCHED_RR对SCHED_FIFO做出了一些增强功能。从实质上看,它还是SCHED_FIFO调用策略。它使用最大运行时间来限制当前进程的运行,当运行时间大于等于最大运行时间的时候,当前线程将被切换并放置于相同优先级队列的最后。这样做的好处是其他具有相同级别的线程能在“自私“线程下执行。
1.获得线程可以设置的最高和最低优先级,policy: 可以取三个值(SCHED_FIFO、SCHED_RR、SCHED_OTHER)
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
注意:对于 SCHED_OTHER 策略,sched_priority 只能为 0。对于 SCHED_FIFO,SCHED_RR 策略,sched_priority 从 1 到 99。
2.设置和获取优先级通过以下两个函数
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; //设置优先级
了解sched_param结构体
struct sched_param
{
int __sched_priority; // 所要设定的线程优先级
};
//param是struct sched_param类型的指针,它仅仅包含一个成员变sched_priority,指明所要设置的静态线程优先级。
3.改变策略(静态改变策略和设置优先级)
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int policy);
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include "errors.h" void *thread_routine(void *arg)
{
int my_policy;
struct sched_param my_param; #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined(sun)
pthread_getschedparam(pthread_self(), &my_policy, &my_param);
printf("thread_routine running at %s/%d\n",
(my_policy == SCHED_FIFO ? "FIFO"
: (my_policy == SCHED_RR ? "RR"
: (my_policy == SCHED_OTHER ? "OTHER"
: "unknown"))),
my_param.sched_priority);
#else
printf("thread_routine running\n");
#endif
return NULL;
} int main(int argc, char *argv[])
{
pthread_t thread_id;
pthread_attr_t thread_attr;
int thread_policy;
struct sched_param thread_param;
int status, rr_min_priority, rr_max_priority; pthread_attr_init(&thread_attr); #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined(sun)
pthread_attr_getschedpolicy(&thread_attr, &thread_policy);
pthread_attr_getschedparam(&thread_attr, &thread_param);//获取优先级
printf("Default policy is %s, priority is %d\n",
(thread_policy == SCHED_FIFO ? "FIFO"
: (thread_policy == SCHED_RR ? "RR"
: (thread_policy == SCHED_OTHER ? "OTHER"
: "unknown"))),
thread_param.sched_priority); status = pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);//改变策略
if(status != 0)
printf("Unable to set SCHED_RR policy.\n");
else
{
rr_min_priority = sched_get_priority_min(SCHED_RR);//看当前策略下能设置优先级的范围
if(rr_min_priority == -1)
errno_abort("Get SCHED_RR min priority");
rr_max_priority = sched_get_priority_max(SCHED_RR);
if(rr_max_priority == -1)
errno_abort("Get SCHED_RR max priority");
thread_param.sched_priority = (rr_min_priority + rr_max_priority)/2;//静态改变优先级(线程运行之前)
printf("SCHED_RR priority range is %d to %d: using %d\n",
rr_min_priority, rr_max_priority, thread_param.sched_priority);
pthread_attr_setschedparam(&thread_attr, &thread_param);
printf("Creating thread at RR/%d\n", thread_param.sched_priority);
pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED); //无论何时,当你需要控制一个线程的调度策略或优先级时,必须将inheritsched属性设置为PTHREAD_EXPLICIT_SCHED。
}
#else
printf("Priority scheduling not supported\n");
#endif
pthread_create(&thread_id, &thread_attr, thread_routine, NULL);
pthread_join(thread_id, NULL);
printf("Main exiting\n");
return 0;
}
//运行结果
./sched_attr
Default policy is OTHER, priority is 0
SCHED_RR priority range is 1 to 99: using 50
Creating thread at RR/50
Main exiting
4.继承调度属性
我手动设置了调度策略或优先级时,必须显示的设置线程调度策略的inheritsched属性,因为pthread没有为inheritsched设置默认值。所以在改变了调度策略或优先级时必须总是设置该属性。
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
总结:
5.直接设置正在运行的线程的调度策略和优先级(动态设置线程的调度策略和优先级)
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.实现不允许应用程序将参数改动为特定的值
注意:当pthread_setschedparam函数的参数 policy == SCHED_RR 或者 SCHED_FIFO 时,程序必须要在超级用户下运行
pthread_setschedparam 函数改变在运行线程的调度策略和优先级肯定就不用调用函数来设置inheritsched属性了:pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED); 因为该函数设置的对象是pthread_attr_t
/*
* sched_thread.c
* Demonstrate dynamic scheduling policy use.
*/
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include "errors.h" #define THREADS 5 typedef struct thread_tag {
int index;
pthread_t id;
} thread_t; thread_t threads[THREADS];
int rr_min_priority; void *thread_routine(void *arg)
{
thread_t *self = (thread_t *)arg;
struct sched_param my_param;
int my_policy;
int status; my_param.sched_priority = rr_min_priority + self->index;
if(pthread_setschedparam(self->id, SCHED_RR, &my_param) != 0)//线程运行时设置策略和优先值
printf("pthread_setschedparam failed\n");
pthread_getschedparam(self->id, &my_policy, &my_param);
printf("thread_routine %d running at %s/%d\n",
self->index,
(my_policy == SCHED_FIFO ? "FIFO"
: (my_policy == SCHED_RR ? "RR"
: (my_policy == SCHED_OTHER ? "OTHER"
: "unknown"))),
my_param.sched_priority); return NULL;
} int main(int argc, char *argv[])
{
int count; rr_min_priority = sched_get_priority_min(SCHED_RR);
if(rr_min_priority == -1){
errno_abort("Get SCHED_RR min priority");
}
for(count = 0; count < THREADS; count++){
threads[count].index = count;
pthread_create(&threads[count].id, NULL,
thread_routine, (void *)&threads[count]);
}
for(count = 0; count < THREADS; count++){
pthread_join(threads[count].id, NULL);
}
printf("Main exiting\n"); return 0;
}
//运行结果
gcc -Wall -lpthread -o sched_thread sched_thread.c
./sched_thread
pthread_setschedparam failed
pthread_setschedparam failed
pthread_setschedparam failed
thread_routine 1 running at OTHER/0
thread_routine 3 running at OTHER/0
pthread_setschedparam failed
pthread_setschedparam failed
thread_routine 2 running at OTHER/0
thread_routine 4 running at OTHER/0
thread_routine 0 running at OTHER/0
Main exiting
//以上失败,一下运行用:sudo ./sched_thread (输入密码)时,函数 pthread_setschedparam(self->id, SCHED_RR, &my_param) 调用成功。将SCHED_RR换成SCHED_FIFO,结果也是一样的。
digdeep@ubuntu:~/pthread/learnthread$ sudo ./sched_thread
[sudo] password for digdeep:
thread_routine 1 running at RR/2
thread_routine 3 running at RR/4
thread_routine 2 running at RR/3
thread_routine 0 running at RR/1
thread_routine 4 running at RR/5
Main exiting
digdeep@ubuntu:~/pthread/learnthread$
它有很多改进的地方,比如可以使用虚优先级(在程序中加入虚实影射表)等
【转】 pthread设置线程的调度策略和优先级的更多相关文章
- pthread调度策略,优先级和竞争范围
实时调度:操作系统在有限的时间内提供特定水平的服务能力.受限制的响应时间不一定是块的反应,意味着可预知的响应速度.如果系统定义_POSIX_THRAED_PRIORITY_SCHEDULING,它为线 ...
- Linux-pthread如何设置线程的优先级
设置线程优先级的函数: int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param ...
- java 22 - 6 多线程之线程调度和设置线程的优先级
线程调度 假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到 CPU时间片,也就是使用权,才可以执行指令. 那么Java是如何对线程进行调用的呢? 线程有两种调 ...
- Java如何设置线程的优先级?
在Java编程中,如何设置线程的优先级? 以下示例如何使用setPriority()方法来设置线程的优先级. package com.yiibai; public class SettingPrior ...
- Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...
- Java:多线程<四> Lock、停止线程、守护线程、join、优先级&yield
Java1.5以后,Condition将Object监视器方法(wait, notify, notifyAll)分解成截然不同的对象,以便通过这些对象与任意Lock实现组合使用为每个对像提供多个等待s ...
- 细说C#多线程那些事 - 线程同步和多线程优先级
上个文章分享了一些多线程的一些基础的知识,今天我们继续学习. 一.Task类 上次我们说了线程池,线程池的QueueUserWorkItem()方法发起一次异步的线程执行很简单 但是该方法最大的问题是 ...
- Windows内核之线程的调度,优先级,亲缘性
1 调度 Windows不是实时操作系统,它是抢占式多线程操作系统.在如果全部优先级同样的情况下,CPU对线程的调度原则是每隔20m就会切换到下一个线程,依据Context中的IP和SP来接着运行上次 ...
- pthread之线程堆栈
转:http://blog.csdn.net/horstlinux/article/details/7666032 //先来讲说线程内存相关的东西,主要有下面几条: //进程中的所有的线程共享相同的地 ...
随机推荐
- [07-01]http网页提示含义
出现较多的一些网页代码提示的意思: 100 - 继续. 101 - 切换协议. 110 重新启动标记答复. 120 服务已就绪,在 nnn 分钟后开始. 125 数据连接已打开,正在开始传输. 150 ...
- [math] sagemath
官网首页:http://www.sagemath.org 首页里引出的两个教程 http://www.gregorybard.com/Sage.html http://sagebook.gforge. ...
- da5_random模块
import random #标准模块,用来取随机数 print(random.randint(1,100)) #随机取一个整数,顾头顾尾 print(random.uniform(1,900)) # ...
- Linux之grep的使用
基本介绍 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全 ...
- darknet集成遇到的问题以及解决方法
将darknet集成进工程时,遇到了一些问题,下面记录一下解决方法: 集成步骤: 首先在yolo编译的时候,需要将三个开关打开: #define GPU#define CUDNN#define OPE ...
- vue.js 之 watch 详解
接我上篇博客的例子: 在上面代码中,当我们修改 firstName 或 lastName 后,watch 监听每次修改变化的新值,然后计算输出 fullName:此时 watch 的一个缺点是,最初绑 ...
- @Value("${xxxx}")注解的配置及使用
代码中的用法 Spring 通过@Value注解获取*.porperties文件code的内容,然后赋值给使用该注解的Code属性上. @Value("${code}") priv ...
- bugfree3.0.1-BUG解决方案修改
该篇内容来自文档“masterBugFree2.pdf”,记录在这里. 1.如何将解决方案改为中文 在\Bugfree\Lang\ZH_CN_UTF-8 \_COMMON.php 文件中做如下修改/* ...
- ivew定制主题 less ^3.0 时报错 .bezierEasingMixin(); Inline JavaScript is not enabled. Is it set in your options?
按照 ivew 提供的方法定制主题,创建一个 less 文件,在其中覆盖变量,再在 main.js 中引入.戳这里 出现报错: 问题貌似是在于 less 版本...两种解决方法: 1.打开项目pack ...
- 对象的创建与OOP-Klass模型
1.JVM中OOP-KLASS模型 在JVM中,使用了OOP-KLASS模型来表示java对象,即:1.jvm在加载class时,会创建instanceKlass,表示其元数据,包括常量池.字段.方法 ...