Linux 线程调度与优先级

Linux内核的三种调度策略

1,SCHED_OTHER:分时调度策略。

它是默认的线程分时调度策略,所有的线程的优先级别都是0,线程的调度是通过分时来完成的。简单地说,如果系统使用这种调度策略,程序将无法设置线程的优先级。请注意,这种调度策略也是抢占式的,当高优先级的线程准备运行的时候,当前线程将被抢占并进入等待队列。这种调度策略仅仅决定线程在可运行线程队列中的具有相同优先级的线程的运行次序。

2,SCHED_FIFO:实时调度策略,先到先服务。一旦占用cpu则一直运行。一直运行直到有更高优先级任务到达或自己放弃。

它是一种实时的先进先出调用策略,且只能在超级用户下运行。这种调用策略仅仅被使用于优先级大于0的线程。它意味着,使用SCHED_FIFO的可运行线程将一直抢占使用SCHED_OTHER的运行线程J。此外SCHED_FIFO是一个非分时的简单调度策略,当一个线程变成可运行状态,它将被追加到对应优先级队列的尾部。当所有高优先级的线程终止或者阻塞时,它将被运行。对于相同优先级别的线程,按照简单的先进先运行的规则运行。我们考虑一种很坏的情况,如果有若干相同优先级的线程等待执行,然而最早执行的线程无终止或者阻塞动作,那么其他线程是无法执行的,除非当前线程调用如pthread_yield之类的函数,所以在使用SCHED_FIFO的时候要小心处理相同级别线程的动作。

3,SCHED_RR:实时调度策略,时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平。

鉴于SCHED_FIFO调度策略的一些缺点,SCHED_RR对SCHED_FIFO做出了一些增强功能。从实质上看,它还是SCHED_FIFO调用策略。它使用最大运行时间来限制当前进程的运行,当运行时间大于等于最大运行时间的时候,当前线程将被切换并放置于相同优先级队列的最后。这样做的好处是其他具有相同级别的线程能在“自私“线程下执行。

系统创建线程时,默认的线程是SCHED_OTHER。所以如果我们要改变线程的调度策略的话,可以通过下面的这个函数实现:

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

Linux线程优先级设置

首先,可以通过以下两个函数来获得线程可以设置的最高和最低优先级,函数中的策略即上述三种策略的宏定义:

int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);

SCHED_OTHER是不支持优先级使用的,而SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高。

设置和获取优先级通过以下两个函数:

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使用了下面的这个数据结构:

struct sched_param
{
    int __sched_priority; //所要设定的线程优先级
};

例如:

 param.sched_priority = 51; //设置优先级

测试程序

#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <assert.h>

//打印当前的线程调度策略
static int get_thread_policy(pthread_attr_t *attr)
{
  int policy;
  int rs = pthread_attr_getschedpolicy(attr,&policy);
  assert(rs==0);
  switch(policy)
  {
  case SCHED_FIFO:
    printf("policy= SCHED_FIFO\n");
    break;
  case SCHED_RR:
    printf("policy= SCHED_RR\n");
    break;
  case SCHED_OTHER:
    printf("policy=SCHED_OTHER\n");
    break;
  default:
    printf("policy=UNKNOWN\n");
    break;
  }
  return policy;
}

//打印当前调度策略线程的最高和最低优先级
static void show_thread_priority(pthread_attr_t *attr,int policy)
{
  int priority = sched_get_priority_max(policy);
  assert(priority!=-1);
  printf("max_priority=%d\n",priority);
  priority= sched_get_priority_min(policy);
  assert(priority!=-1);
  printf("min_priority=%d\n",priority);
}

//打印当前线程的优先级
static int get_thread_priority(pthread_attr_t *attr)
{
  struct sched_param param;
  int rs = pthread_attr_getschedparam(attr,&param);
  assert(rs==0);
  printf("priority=%d\n",param.__sched_priority);
  return param.__sched_priority;
}

//设置线程线程的调度策略
static void set_thread_policy(pthread_attr_t *attr,int policy)
{
  int rs = pthread_attr_setschedpolicy(attr,policy);
  assert(rs==0);
  get_thread_policy(attr);
}

int main(void)
{
  pthread_attr_t attr;
  struct sched_param sched;
  int rs;
  rs = pthread_attr_init(&attr);
  assert(rs==0);

  //获取默认的线程调度策略
  printf("==    Show current configuration of priority    ==\n");
  int policy = get_thread_policy(&attr);
  show_thread_priority(&attr,policy);
  //打印当前线程的优先级
  printf("show priority of current thread\n");
  int priority = get_thread_priority(&attr);

   printf("==   Show different Scheduling method priority   ==\n");
  //获取SCHED_FIFO调度策略的最高和最低优先级
  printf("show SCHED_FIFO of priority:\n");
  show_thread_priority(&attr,SCHED_FIFO);

 //获取SCHED_RR调度策略的最高和最低优先级
  printf("show SCHED_RR of priority:\n");
  show_thread_priority(&attr,SCHED_RR);

  printf("==        Set thread policy        == \n");
  //设置线程的调度属性为SCHED_FIFO
  printf("set SCHED_FIFO policy:\n");
  set_thread_policy(&attr,SCHED_FIFO);
  priority = get_thread_priority(&attr);
  sched.__sched_priority = 99;
  pthread_attr_setschedparam(&attr,&sched);
  priority = get_thread_priority(&attr);

  //设置线程的调度属性为SCHED_FIFO
  printf("set SCHED_RR policy:\n");
  set_thread_policy(&attr,SCHED_RR);
  priority = get_thread_priority(&attr);
  sched.__sched_priority = 55;
  pthread_attr_setschedparam(&attr,&sched);
  priority = get_thread_priority(&attr);

  //恢复线程的调度策略
  printf("Restore current policy:\n");
  set_thread_policy(&attr,policy);

  rs = pthread_attr_destroy(&attr);
  assert(rs==0);
  return 0;
}

原文地址:https://www.cnblogs.com/xiaojianliu/p/9689118.html

时间: 2024-08-05 16:20:41

Linux 线程调度与优先级的相关文章

Linux 线程调度与优先级设置

转载:http://blog.csdn.net/a_ran/article/details/43759729 Linux内核的三种调度策略: 1,SCHED_OTHER 分时调度策略, 2,SCHED_FIFO实时调度策略,先到先服务.一旦占用cpu则一直运行.一直运行直到有更高优先级任务到达或自己放弃 3,SCHED_RR实时调度策略,时间片轮转.当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾.放在队列尾保证了所有具有相同优先级的RR任务的调度公平 Linux线程优先级设置   首

Linux 线程调度的优先级

Linux内核的三种调度策略: 1.SCHED_OTHER 分时调度策略 2.SCHED_FIFO实时调度策略,先到先服务.一旦占用cpu则一直运行.一直运行直到有更高优先级任务到达或自己放弃 3.SCHED_RR实时调度策略,时间片轮转.当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾.放在队列尾保证了所有具有相同优先级的RR任务的调度公平 Linux线程优先级设置: 首先,可以通过以下两个函数来获得线程可以设置的最高和最低优先级,函数中的策略即上述三种策略的宏定义: int sch

浅析Linux线程调度

在Linux中,线程是由进程来实现,线程就是轻量级进程( lightweight process ),因此在Linux中,线程的调度是按照进程的调度方式来进行调度的,也就是说线程是调度单元.Linux这样实现的线程的好处的之一是:线程调度直接使用进程调度就可以了,没必要再搞一个进程内的线程调度器.在Linux中,调度器是基于线程的调度策略(scheduling policy)和静态调度优先级(static scheduling priority)来决定那个线程来运行. 对于下面三种调度策略SCH

Linux线程调度引起的业务问题

一. 问题现象 1.业务组播出向报文偶尔有延迟: 2.单播出向报文平滑 二. 分析及定位 使用wireshark分析了组播出向报文的抓包,报文无丢包,但是IO 输出流量显示有burst和掉坑现象. 波形和抓包文件分析如下图: 后来在接收侧抓包,并分析日志,接收方没有出现丢包问题,但是有接收码流不足,导致收包不及时,业务不流畅. 通过在系统内核发包udp_sendmsg函数打点,发现有时候有300ms+没有报文发出,说明发包线程被阻塞. 下面是监控组播出向发包函数udp_sendmsg的打点记录日

Linux资源管理-IO优先级

前一篇博客介绍了利用 cgroup 来控制进程的 CPU和内存使用情况, 这次补上使用 cgroup 来控制进程的IO优先级的方法. 前提条件 如果想控制进程的IO优先级, 需要内核的支持, 内核编译时需要打开下面2个参数. CONFIG_BLK_CGROUP=y CONFIG_CFQ_GROUP_IOSCHED=y 查看是否开启这2个内核编译选项的方法很简单: [email protected]113:~# grep -i 'blk_cgroup' /boot/config-`uname -r

Windows核心编程笔记(5)----线程调度,优先级

1.操作系统线程调度过程 每个线程都有一个上下文CONTEXT结构体,保存在线程的内核对象中,这个上下文中保存了线程上一次执行时CPU寄存器 的状态.每隔固定时间,Windows会查看所有当前存在的线程内核对象,其中只有一些是可调度的.Windows在可调度的 线程中选择一个,并将上次保存到线程上下文中的数据载入CPU寄存器中.(上下文切换) CPU时间片到后,Windows移出这个线程,把CPU寄存器信息保存到线程上下文中,切换到另一个线程,如此循环. 2.线程的挂起和恢复 调用CreateP

第7章 线程调度、优先级和亲缘性(2)

7.7 在实际上下文中谈CONTEXT结构 (1)线程CONTEXT记录线程的状态(如CPU各寄存器状态),以供下次调度时从停止处继续. (2)CONTEXT的结构(要获得或设置时,必须在Context.ContextFlags设置相应的标志) 标志 说明 CONTEXT_CONTROL 控制寄存器,如EIP.ESP,EBP等 CONTEXT_INTEGER 整数寄存器,如EDI.ESI.EBX.EDX.ECX.EAX等 CONTEXT_FLOATING_POINT 浮点寄存器,将寄存器结果返回

第7章 线程调度、优先级和亲缘性

7.1 线程的挂起和恢复 (1)线程挂起 ①创建时(如CreateProcess.CreateThread),传入CREATE_SUSPENDED标志 ②用SuspendThread挂起线程.这个函数可以挂起自己,也可以挂起其它线程(只要有线程句柄) ③线程在挂机计数不为0或没有消息队列没有消息时,是不可调度的(没时间片) (2)线程恢复:ResumeThread,返回前一个挂起计数,否则返回0xFFFFFFFF. ①一个线程可以被多次挂起,最多可以挂起MAXIMUNM_SUSPEND_COUN

Linux 线程调度

1.线程sleep()后,会让出cpu的时间片,交由其他线程进行抢占cpu. 线程之间正常的切换是依靠时间片的. 当主线程没有结束,且其在所占有的时间片内,并没有结束自己的工作,此时,子线程将会抢占cpu时间片. 参考帖子以及下面的评论:https://blog.csdn.net/harry_lyc/article/details/6055734#reply 原文地址:https://www.cnblogs.com/xuelisheng/p/9277401.html