百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

详细解析Linux系统中进程/线程的调度优先级规则

wptr33 2025-02-19 14:10 25 浏览

调度机制的原理

进程和线程的调度都是由内核来完成的。操作系统内核包含一个调度器(scheduler),负责管理和调度所有进程和线程。调度器根据特定的调度策略和优先级规则来决定哪个进程或线程应该获得CPU资源,从而实现多任务和并发执行。

调度过程分为以下几个步骤:

预选:调度器会从进程和线程列表中选择一个候选者,作为接下来要运行的执行单元。

上下文切换:调度器会将当前运行的进程或线程的状态(包括寄存器、程序计数器等)保存到内核数据结构中,然后将选定的候选者的状态加载到CPU中。

执行:选定的进程或线程开始运行。它会在用户态执行指令,直到发生某个事件(如时间片用完、系统调用、中断等),需要重新进行调度。

再次调度:当一个进程或线程无法继续运行时(例如,因为它需要等待I/O操作完成),调度器会再次执行预选和上下文切换,将另一个进程或线程调度到CPU上。

在整个过程中,线程会在用户态和内核态之间切换。当线程执行完一个时间片或遇到需要内核介入的事件时(如系统调用、中断处理等),它会切换到内核态,让调度器重新分配资源。调度器在内核态运行,可以确保对系统资源的控制和管理。

在多核处理器系统中,调度器可以同时调度多个进程或线程在不同的核心上运行,以实现真正的并行执行。总之,进程和线程的调度都是通过内核来完成的,内核调度器负责管理和分配CPU资源,以实现高效的多任务和并发执行。

查询当前进程或线程的资源使用情况

在Linux中,可以使用getrusage()系统调用查询当前进程或线程的资源使用情况,包括本次被调度的时间,另外,通过分析/proc//sched文件中的调度统计信息,可以间接了解进程的调度情况。

getrusage()会返回一个rusage结构,其中包含了各种资源使用信息。以下是rusage结构的定义:

struct rusage {
   struct timeval ru_utime; /* 用户态使用的CPU时间 */
   struct timeval ru_stime; /* 内核态使用的CPU时间 */
   // ...其他资源使用信息
};

getrusage()函数的原型如下:

int getrusage(int who, struct rusage *usage);

who参数可以是以下值之一:

  • RUSAGE_SELF:查询当前进程的资源使用情况。
  • RUSAGE_CHILDREN:查询已终止且已收集的所有子进程的资源使用情况。
  • RUSAGE_THREAD(Linux-specific):查询当前线程的资源使用情况。

要查询本次被调度的时间,可以将ru_utime和ru_stime的值相加,得到总的CPU时间。

调度优先级基本知识

  • cpu分配资源的先后顺序就是优先级
  • 优先权高的进程有优先执行的权利
  • 可以让进程运行在指定的cpu上,改善系统整体性能
  • 用top或者ps -l查看进程会发现有PR(PRI) NI两个字段:NI 是优先值,是用户层面的概念, PR是进程的实际优先级, 是给内核(kernel)看(用)的。

Linux进程调度的三种策略

SCHED_OTHER,分时调度策略

该策略是是默认的Linux分时调度(time-sharing scheduling)策略,它是Linux线程默认的调度策略。SCHED_OTHER策略的静态优先级总是为0,对于该策略列表上的线程,调度器是基于动态优先级(dynamic priority)来调度的,动态优先级是跟nice中相关(nice值可以由接口nice, setpriority,sched_setattr来设置),该值会随着线程的运行时间而动态改变,以确保所有具有SCHED_OTHER策略的线程公平运行

SCHED_FIFO,实时调度策略,先到先服务。

根据进程的优先级进行调度,一旦抢占到 CPU 则一直运行,直到自己主动放弃或被被更高优先级的进程抢占;

SCHED_RR,实时调度策略,时间片轮转

在 SCHED_FIFO 的基础上,加上了时间片的概念。当一个进程抢占到 CPU 之后,运行到一定的时间后,调度器会把这个进程放在 CPU 中,当前优先级进程队列的末尾,然后选择另一个相同优先级的进程来执行;

Linux 线程优先级

进程

调度策略

优先级

说明

普通进程

SCHED_OTHER或SCHED_NORMAL

100-139

这个区间的优先级又称为静态优先级,不会随着时间而改变,内核不会修改它,只能通过系统调用nice去修改,静态优先级数值越大,进程的优先级越小,分配的基时间量就越少。普通进程几乎是无法分到时间片的(只能分到5%的CPU时间)。

static priority=nice+20+MAX_RT_PRIO,nice值[-20,19],MAX_RT_PRIO默认为100,这样做的好处是,任何内核态进程优先级都大于用户态的进程.;

实时进程

SCHED_FIFO或SCHED_RR

0-99

只有在下述事件之一发生时,实时进程才会被另外一个进程取代

1. 进程被另外一个具有更高实时优先级的实时进程抢占

2. 进程执行了阻塞操作并进入睡眠

3. 进程停止(处于TASK_STOPPED 或TASK_TRACED状态)或被杀死

4. 进程通过调用系统调用sched_yield(),自愿放弃CPU5. 进程基于时间片轮转的实时进程(SCHED_RR),而且用完了它的时间片.




这张图表示的是内核中的优先级,分为两段。

前面的数值 0-99 是实时任务,后面的数值 100-139 是普通任务。

数值越低,代表这个任务的优先级越高。

以上是从内核角度来看的优先级。

我们在应用层创建线程的时候,设置了一个优先级数值,这是从应用层角度来看的优先级数值。

但是内核并不会直接使用应用层设置的这个数值,而是经过了一定的运算,才得到内核中所使用的优先级数值(0 ~ 139)。

对于实时任务

我们在创建线程的时候,可以通过下面这样的方式设置优先级数值(0 ~ 99):

struct sched_param param;
param.__sched_priority = xxx;

当创建线程函数进入内核层面的时候,内核通过下面这个公式来计算真正的优先级数值:

kernel priority = 100 - 1 - param.__sched_priority

如果应用层传入数值 0,那么在内核中优先级数值就是 99(100 - 1 - 0 = 99),在所有实时任务中,它的优先级是最低的。

如果应用层传输数值 99,那么在内核中优先级数值就是 0(100 - 1 - 99 = 0),在所有实时任务中,它的优先级是最高的。

因此,从应用层的角度看,传输人优先级数值越大,线程的优先级就越高;数值越小,优先级就越低。

与内核角度是完全相反的!

对于普通任务

调整普通任务的优先级,是通过 nice 值来实现的,内核中也有一个公式来把应用层传入的 nice 值,转成内核角度的优先级数值:

kernel prifoity = 100 + 20 + nice

nice 的合法数值是:-20 ~ 19。

如果应用层设置线程 nice 数值为 -20,那么在内核中优先级数值就是 100(100 + 20 + (-20) = 100),在所有的普通任务中,它的优先级是最高的。

如果应用层设置线程 nice 数值为 19,那么在内核中优先级数值就是 139(100 +20 +19 = 139),在所有的普通任务中,它的优先级是最低的。

因此,从应用层的角度看,传输人优先级数值越小,线程的优先级就越高;数值越大,优先级就越低。

与内核角度是完全相同的!

top中的PR和NI


top命令中pri的计算方法

说明

普通进程

top_pr=static_priority-100

static_priority取值是[100,139],所以top_pri取值是[0,39]

实时进程

top_pri=-1-real_time_priority

chrt命令就是修改实时进程的优先级,比如给进程12345分配优先级为93,chrt -p 93 12345,则top命令pri值显示的是-94。有的实时进程的pri值显示的是rt,没有具体显示数值




多核调度

对于多核处理器,分布不同核时,调度策略、优先级,都不起作用!(准确的说:调度策略和优先级,在线程所在的那个 CPU 中是起作用的)

相关推荐

开发者必看的八大Material Design开源项目

MaterialDesign是介于拟物和扁平之间的一种设计风格,自从它发布以来,便引起了很多开发者的关注,在这里小编介绍在Android开发者当中里最受青睐的八个MaterialDesign开源项...

另类插这么可爱,一定是…(另类t恤)

IT之家(www.ithome.com):另类插图:这么可爱,一定是…OSXMavericks和Yosemite打破了苹果对Mac操作系统传统的命名方式,使用加州的某些标志性景点来替换猫...

Android常用ADB命令(安卓adb工具是什么)

杀死应用①根据包名获取APP的PIDadbshellps|grep应用包名②执行kill命令...

微软Mac版PowerPoint测试Reading Order Pane功能

IT之家5月20日消息,微软公司昨日(5月19日)发布博文,邀请Microsoft365Insiders成员,测试macOS新版PowerPoint演示文稿应用,重点引入...

Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍

前言不同于iOS,Xamarin在VisualStudio中针对Android,可以直接设计使用者界面.在本篇教学文章中,笔者会针对Android的专案目录结构以及基本控制项进行介绍,包...

用云存储30分钟快速搭建APP,你信吗?

背景不管你承认与否,移动互联的时代已经到来,这是一个移动互联的时代,手机已经是当今世界上引领潮流的趋势,大型的全球化企业和中小企业都把APP程序开发纳入到他们的企业发展策略当中。但随着手机APP上传的...

谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果

Pine发自凹非寺量子位|公众号QbitAI当你拍照片时,“模特不好好配合”怎么办?...

iOS文本编辑控件UITextField和UITextVie

记录一个菜鸟的IOS学习之旅,如能帮助正在学习的你,亦枫不胜荣幸;如路过的大神如指教几句,亦枫感激涕淋!细心的朋友可能已经注意到了,IOS学习之旅系列教程在本篇公众号的文章中,封面已经换成美女图片了,...

Android入门图文教程集锦(android 入门教程)

Android入门视频教程集锦AndroidStudio错误gradientandroid:endXattributenotfound...

如何使用Android自定义复合视图(如何使用android自定义复合视图)

在最近的一个客户应用中,我遇到了一个需求,根据选定的值来生成指定数量的编辑框字段,这样用户可以输入人物信息。最初我的想法是把这些逻辑放到Fragment中,只是根据选中值的变化来向线性布局容器中增加编...

原生安卓开发app的框架frida常用关键代码定位

前言有时候可能会对APP进行字符串加密等操作,这样的话你的变量名等一些都被混淆了,看代码就可能无从下手...

教程10 | 三分钟搞定一个智能输入法程序

一案例描述1、考核知识点网格布局线性布局样式和主题Toast2、练习目标掌握网格布局的使用掌握Toast的使用掌握线性布局的使用...

(Android 8.1) 功能与新特性(android的功能)

和你一起终身学习,这里是程序员AndroidAndroid8.1(API级别27)为用户和开发人员引入了各种新特性和功能。本文档重点介绍了开发人员的新功能。通过本章阅读,您将获取到以下内容:Andr...

怎样设置EditText内部文字被锁定不可删除和修改

在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白了就是不可操作,只能在后面输入内容。在E...

如何阻止 Android 活动启动时 EditText 获得焦点

技术背景在Android开发中,当活动启动时,EditText有时会自动获得焦点并弹出虚拟键盘,这可能不是用户期望的行为。为了提升用户体验,我们需要阻止...