操作系统——线程调度

news2024/9/30 9:23:06

0.关注博主有更多知识

操作系统入门知识合集

目录

6.1线程调度概念

思考题:

6.2典型调度算法

思考题:

6.3Linux线程调度

6.1线程调度概念

在第四章曾经介绍过,线程是操作系统调度的基本单位,那么本篇就不再以进程的视角去看待调度问题了,读者可以把进程理解为只有一个线程的线程。我们曾经介绍过分时操作系统,那么当一个线程的时间片结束之后,操作系统需要选择一个新的线程来占有CPU。那么线程调度的定义就是:在合适的时候以一定的策略选择一个就绪线程投入运行

操作系统需要考虑以下几个点:

  1.调度时机:操作系统必须选择一个合适的时机去调度线程,这个时机可以是线程的时间片结束、可以是被其他线程抢占、亦或是被迫发生中断......

  2.调度策略:操作系统需要选择一个合适的调度策略去调度线程,也可以理解为调度算法。每一种算法都有好有坏,每一种算法都能会对效率产生不同的影响。

  3.调度的指标:线程的调度可不是一句话盖过这么轻松,操作系统必须考虑以下几个指标:

    1)响应速度尽可能快:这就意味着当要发生调度时,调度的过程必须快。特别是针对用户与计算机交互的操作系统,内部一定会频繁地发生线程调度、切换,操作系统必须有能力让处理调度的时间尽可能短,从而使用户在宏观上感觉不到延迟。

    2)线程的处理尽可能快:因为要频繁发生调度,这就意味着线程不能在CPU上待太长时间。也就是说无论是硬件还是操作系统,他们对任务的处理都必须尽可能快。

    3)操作系统吞吐量尽可能大:在单位时间内,调度更多的线程,就意味这这款操作系统的吞吐量更大。

    4)对所有线程要公平:不能让某个线程频繁被调度,也不能让某个线程迟迟不被调度。也就是说要避免调度带来的饥饿问题。

    5)避免饥饿

    6)避免死锁

    ......

    这些调度的指标(原则),他们之间是相互存在矛盾的。例如1)和2),在操作系统当中存在成百上千个任务,所以他们之间要频繁地发生调度,就算调度的过程再快,它依然会影响线程的单位处理时间,也就是说本来在单位时间内可以处理1000条指令,但因为调度把单位时间给消耗了,此时只能执行400条指令了。所以在实际操作系统的设计中,会根据用户的习惯来增强某一侧重点:例如用户注重硬实时任务,那么操作系统的设计更加侧重指标1)。

思考题:

1.你认为Windows和Linux重点侧重哪些调度指标?

Windows和Linux都是面向用户的操作系统,它们必须优先考虑用户的需求,所以非常侧重调度的响应速度;其次,Windows是一款多任务多并发的操作系统,所以Windows也要确保具有较高的吞吐量。

6.2典型调度算法

先来先服务调度(First Come First Serve):

  1.算法:操作系统按照作业创建的先后来挑选作业,先创建的作业优先被操作系统运行

  2.特点:容易实现但效率不高。FCFS算法只考虑了作业的等候时间,而没有考虑运行时间的长短。也就是说一个晚来但是运行时间很短的作业可能要等待很长时间才可能被投入运行。因此FCFS算法不利于短作业。

短作业有限调度算法(Short Job First):

  1.算法:参考运行时间,选取运行时间最短的作业投入运行

  2.特点:容易实现但效率不高。SJF算法忽视了作业的等待时间,一旦有一个来的早但是很大的作业那么将长时间得不到调度,容易造成饥饿。

响应比高者优先调度算法:

  1.响应比定义:作业的响应时间(等待时间+运行时间)与运行时间的比值。响应比=(等待时间+运行时间)/运行时间,可转化成响应比=1+等待时间/运行时间

  2.算法:操作系统会计算每个作业的响应比,选择响应比最高的作业先投入运行

  3.特点:

    1)如果作业的等待时间相同,则运行时间越短的作业,其响应比越高,因此越容易被调度。因而有利于短作业。

    2)如果作业的运行时间相同,则等待时间越长的作业,其响应比越高,因此越容易被调度。因而有利于等候长的作业。

    3)对于运行时间长的作业,其优先级可以随等待时间的增加而提高,当其等待足够久的时候,就能够获得CPU。

优先数调度算法:

  1.算法:根据线程优先数,把CPU分配给优先级最大的线程。优先数=静态优先数+动态优先数。

  2.静态优先数:线程创建时就确定了,在整个运行期间不再改变

  3.动态优先数:动态优先数在线程运行期间可以改变

  4.静态优先数的确定:操作系统会基于线程所需资源的多少、运行时间的长短、类型(IO/CPU型任务、前台/后台线程、内核/用户线程)来确定静态优先数

  5.动态优先数的确定:当线程占用CPU超过一定时常后,其动态优先数就会降低;当进行I/O操作后,就会发生阻塞,此时动态优先数就会升高;当线程等待超过一定时常时,动态优先数也会升高

循环轮转调度法:

  1.概念:把所有就绪线程按先进先出的原则排成队列,新进来的线程添加到队列的末尾。线程以时间片q为单位轮流使用CPU。在CPU上运行一个时间片的线程被操作系统换下,排到队列的末尾,等候下一轮运行。队列与CPU的逻辑关系类似于环形:

  2.优点:保证了公平性,让每个就绪线程都有平等机会获得CPU;保证了交互性,每个线程等待(N-1)*q的时间后就可以重新获得CPU。

  3.时间片的设置:对于时间片q来说,如果q太大就会导致交互差,甚至退化成FCFS算法;如果q太小,线程之间频繁切换,操作系统的开销就会增大

  4.改进:为了让循环轮转的调度算法更加灵活,每个线程的时间片都是可变的,除此之外,还可以组织多个就绪队列,每个就绪队列的管理策略都不同,这与先前讲过的阻塞队列是一个道理。

由此我们可以退回到操作系统的发展,分时系统的出现是计算机的一次"大革命",直到现在,分时系统依然具有优越性。

思考题:

1.静态优先数的三个因素是如何影响静态优先数的?

线程所需的资源越多,其静态优先数就越大,因为它要尽可能先运行完,尽早释放较多资源给后面的线程使用;运行的时间越长,其静态优先数越大,运行时间长的线程先运行完可以避免总是被运行时间短的线程"插队";偏I/O、处于内核态运行的线程,其静态优先数就越大,因为必须及时处理I/O,否则I/O中的数据可能丢失,而在内核态运行线程往往都是比较重要的任务。

2.动态优先数的三个因素是如何影响静态优先数的?

当在CPU上运行超过一定时间后,其动态优先数就会减小,因为要保证线程调度的公平,不能总是让一个线程占用CPU;当发起I/O操作到I/O操作结束时是一段相对较长的时间,其动态优先数应当被增大,因为长时间等待会发生饥饿问题。

6.3Linux线程调度

在这里需要注意一下,Linux实际上并没有线程这个概念,而是叫做轻量级进程。但我们处于用户视角,我们直接把轻量级进程当成线程来看待。读者需要注意,下面的内容有可能会出现线程,也可能会出现进程,但在调度的角度来看,它们都是一样的。

Linux线程类型:

  1.普通线程:采用动态优先级来调度,调度程序(调度模块)周期性地修改优先级(目的是避免饥饿)

  2.实时进程:采用静态优先级来调度,有用户预先指定优先级,在其整个运行生命周期中不会改变

Linux线程的优先级:

  1.静态优先级:线程创建时由用户指定(用户不指定也可以是默认值)

  2.动态优先级:

    1)在线程运行期间可以按照调度策略来动态改变

    2)非实时线程(普通线程)采用动态优先级,其优先级由操作系统的调度模块计算

    3)只要线程占用CPU,优先级就会随着时间流逝而不断减小

    4)task_struct(进程控制块,因为Linux只有轻量级进程,所以可以把它看成线程控制块)中的counter成员表示动态优先级

调度策略:

  1.PCB的policy成员:在Linux的task_struct(PCB)中有一policy成员指明了进程(线程)调度策略(Linux没有线程,只有轻量级进程):

  2.实时进程(线程)的调度策略:

    1)SCHED_FIFO(先进先出):与FCFS调度算法一样,当前实时进程(线程)一直占用CPU直至退出或阻塞或被抢占,再就绪时会被操作系统添加到相同优先级的就绪队列末尾(Linux没有就绪态,但是有就绪队列)。

    2)SCHED_RR(时间片轮转):与其他实时进程(线程)以循环轮转调度法的方式共同使用CPU,确保了同优先级的多个进程(线程)能够共享CPU

  3.普通进程(线程)的调度策略:使用SCHED_OTHER动态优先级的策略来调度普通进程(线程),其task_struct中的counter成员表示进程(线程)的动态优先级

  4.调度策略的改变:系统调用sched_setscheduler()能够让用户改变调度策略,并且实时进程的子孙进程也是实时进程

调度的依据:

  主要依赖task_struct中有关调度策略的属性:

    1)policy:这个成员记录了调度的策略,用来区分实时进程(线程)和普通进程(线程)

    2)priority:所有的进程(线程)的静态优先级

    3)rt_priority:实时进程(线程)特有的优先级,rt_priority=priority+1000

    4)counter:进程(线程)能够连续运行的时间(实际上动态优先级就可以理解为时间计数器,在CPU上的时间越长其值就越小,最后到0便让出CPU)

动态优先级counter:

  1.counter值的含义:进程(线程)能够连续运行的时间,单位时间为时钟滴答tick。假设时钟中断周期tick为10ms,那么当counter=60时,那么该进程(线程)能够连续运行600ms。较高优先级的进程(线程)的counter值一般都比较大。虽然说counter值表示进程(线程)能够连续运行的时间,但在Linux中,把counter看作动态优先级

  2.counter的初值与priority有关:普通进程(线程)创建时counter的处置为priority的值

  3.counter的改变:时钟中断tick时,当前进程(线程)的counter值减1,直到0时放弃CPU

  4.子进程创建时counter:新建子进程的counter从父进程counter中分一半过来。也就是说,假设父进程的counter值为60,则其创建的子进程counter值为30,其本身的counter修改为30。这样做的目的是防止用户无限制地创建子孙进程而长期占用CPU资源

调度时机:

  1.用户态进程(线程)只能通过中断来发生切换(只能被动发生切换):

    1)例如发生时钟中断、I/O中断、系统调用等不可预知的中断,然后CPU陷入内核处理这些中断处理程序,在处理的过程当中调用schedule()接口实现进程(线程)切换

    2)调用schedule()接口时CPU不能处于内核态,因为这样就相当于赋予用户态进程(线程)很高的权限,对操作系统不安全。在CPU处理中断处理程序要调用schedule()接口之前必须先发生一次态的转换,由内核态返回到用户态,在用户态中调用schedule()接口,并且需要根据need_resched标记来检测是否需要需要调用schedule()接口

  2.内核线程可以直接调用schedule()接口实现进程(线程)切换,这是一种内核主动调度的情形

  3.进程(线程)的调度实质就是发生一次进程(线程)切换,切换的过程与中断很像,但是存在一定的差别:发生中断时,操作系统需要保护CPU当前运行进程(线程)的上下文,然后装入中断处理程序的入口地址;而发生进程(线程)切换时,操作系统不仅需要保护CPU当前运行的进程(线程)的上下文,还要恢复被调度而来的进程(线程)的上下文。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/485649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【操作系统OS】学习笔记第二章 进程与线程(下)【哈工大李治军老师】

基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记&#xff0c;仅进行交流分享。 特此鸣谢李治军老师&#xff0c;操作系统的神作&#xff01; 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0…

基于rke部署的k8s集群如何配置kube-proxy工作在ipvs模式

kube-proxy默认工作在iptables模式下&#xff0c;在集群配置文件cluster.yml中添加如下配置项即可开启ipvs模式。然后执行 rke up 命令使配置生效。

软件测试的ABC

文章目录 一. 衡量软件测试结果的依据—需求1. 什么是需求2. 案例 - 平台支持邮箱注册3. 从测试人员角度看需求 二. 测试用例1. 测试用例的概念2. 案例3. 为什么要有测试用例 三. 软件错误 (BUG)1. 什么是bug2. 如何描述一个bug3. bug的级别4. bug的生命周期5. 如果因为bug和开…

Java面试题总结 | Java面试题总结8- Redis模块(持续更新)

Redis 文章目录 Redisredis的线程模型Redis的Mysql的区别Redis和传统的关系型数据库有什么不同&#xff1f;Redis常见的数据结构zset数据结构Redis中rehash过程redis为什么不考虑线程安全的问题呢Redis单线程为什么还能这么快&#xff1f;为什么Redis是单线程的&#xff1f;red…

【SpringMVC】| SpringMVC执行流程原理 | 常用注解 剥析

MVC目录 一. &#x1f981; MVC模型二. &#x1f981; SpringMVC1. SpringMVC执行流程&#xff08;重点&#xff09;Ⅰ. SpringMVC四大组件Ⅱ. 执行流程 2. RequestMapping3. RequestParam4. ReuqestHeader & CookieValue5. RESTful风格支持Ⅰ. 传统 vs restfulⅡ. PathVar…

5. Docker——先快速入门

本章讲解知识点 Docker 是什么为什么要使用 DockerDocker 引擎Docker 常用命令Docker 生命周期详解虽然我们上一章教大家搭建好了 Kubernetes + Docker 环境,但是我们本章是先从 Docker 讲起,为后面学习 Kubernetes 打好基础。 1. Docker 是什么 Docker 是一种开源的容器化…

spring5源码篇(9)——mybatis-spring整合原理

spring-framework 版本&#xff1a;v5.3.19 spring和mybatis的整合无非主要就是以下几个方面&#xff1a; 1、SqlSessionFactory怎么注入&#xff1f; 2、Mapper代理怎么注入&#xff1f; 3、为什么要接管mybatis事务&#xff1f; 文章目录 一、SqlSessionFactory怎么注入SqlSe…

离散数学_九章:关系(4)

9.4 关系的闭包 1、闭包(closure)的定义2、不同类型的闭包1. 自反闭包(reflexive closure)2. 对称闭包(symmetric closure)3. 传递闭包(transitive closure) 3、闭包的几个定理定理1定理2定理3 - R1∪R2定理4定理5&#x1f4d8;例题&#xff1a; 4、有向图中的路径5、传递闭包1…

2000-2019年30省研发资本存量(含计算过程和原始数据)

2000-2019年30省份研发资本存量&#xff08;含计算过程和原始数据&#xff09;/2000-2019年30个省市R&D资本存量或研发资本存量数据 1、时间&#xff1a;2000-2019年 2、范围&#xff1a;包括30个省市不含西藏 3、指标&#xff1a;省研发资本存量 4、参考文献&#xff…

家用 NAS 服务器搭建 | 网络 | DNS域名解析

1、前言 使用NAS&#xff0c;一般除了在家里通过局域网访问&#xff0c;还会有外网访问的需求&#xff0c;即在外面通过移动网络或者其他网络访问家中的NAS。 正常情况下在外面是没有办法访问家庭网络的&#xff0c;甚至是nas&#xff0c;因为nas获取的是局域网IP&#xff0c;…

【Python】flask

一、Flask教程 Flask是一个免费的web框架&#xff0c;也是一个年轻、充满活力的小型框架&#xff0c;开发文档齐 全&#xff0c;社区活跃度高&#xff0c;有着众多支持者。 Flask的设计目标是实现一个WSGI的微框架&#xff0c; 其核心代码十分简单。 Flask框架在中小型企业中的…

pwn的kali64虚拟机环境搭建记录

自己记着备用&#xff0c;pwn的环境和工具 虚拟机&#xff1a;VMware Workstation Pro Linux版本&#xff1a;kali64 总参考&#xff1a; pwn 环境搭建&#xff08;wsl/vmware&#xff09; pwn入门之环境搭建 目前就装这些&#xff0c;以后改了再更新&#xff08;但愿 安装ka…

第 4 章 HBase 进阶

第 4 章 HBase 进阶 4.1 Master 架构1&#xff09;Meta 表格介绍&#xff1a;&#xff08;警告&#xff1a;不要去改这个表&#xff09; 4.2 RegionServer 架构1&#xff09;MemStore2&#xff09;WAL&#xff08;预写日志&#xff09;3&#xff09;BlockCache 4.3 写流程2&…

使用kubeadm搭建生产环境的多master节点k8s高可用集群

环境centos 7.9 目录 1.对安装 k8s 的节点进行初始化配置 2 通过 keepalivednginx 实现 k8s apiserver 节点高可用 3、kubeadm 初始化 k8s 集群 4.扩容 k8s 控制节点&#xff0c;把 xuegod62 加入到 k8s 集群 5、扩容 k8s 控制节点&#xff0c;把 xuegod64 加入到 k8s 集群…

06_Uboot顶层Makefile分析_前期所做内容

目录 U-Boot顶层Makefile分析 版本号 MAKEFLAGS变量 命令输出 静默输出 设置编译结果输出目录 代码检查 模块编译 获取主机架构和系统 设置目标架构、交叉编译器和配置文件 调用scripts/Kbuild.include 交叉编译工具变量设置 导出其他变量 U-Boot顶层Makefile分析…

Kafka架构原理(三)

三、Kafka架构原理 3.1 整体架构图 一个典型的kafka集群中包含若干个Producer&#xff0c;若干个Broker&#xff0c;若干个Consumer&#xff0c;以及一个zookeeper集群&#xff1b; kafka通过zookeeper管理集群配置&#xff0c;选举leader&#xff0c;以及在Consumer Group发…

软件多语言文案脚本自动化方案

开发高效提速系列目录 软件多语言文案脚本自动化方案 软件多语言文案脚本自动化方案 背景目标整体方案1. 创建文案资源文件2. python脚本开发3. Python脚本执行与管理4. 人员职责分配 PyCharm使用说明1. PyCharm下载2. PyCharm安装配置3. 异常情况解决 总结 博客创建时间&…

中间件漏洞(一)CVE-2013-4547(文件名逻辑漏洞)

目录 1. 了解nginx的工作原理 2. 漏洞原理及举例分析 3. 前端php源码分析 4. 注入思路 5. 漏洞复现 5.1 上传文件并抓包分析 5.2 通过访问文件执行php 注意一点 6. 漏洞修复 1. 了解nginx的工作原理 nginx是以PHP语言为主。像Apache一样&#xff0c;Nginx自身是不支持解…

基于黏菌算法的极限学习机(ELM)回归预测-附代码

基于黏菌算法的极限学习机(ELM)回归预测 文章目录 基于黏菌算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于黏菌算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用黏菌算法对极限学习机进行优化&#xff0c;并…

国民技术N32G430开发笔记(15)- IAP升级 树莓派串口发送数据

IAP升级 树莓派串口发送数据 1、树莓派接入usb转串口模块后&#xff0c;会生成/dev/ttyUSB0节点&#xff0c;因为树莓派内核已经编译usb_serial以及各模块的驱动。 我们直接对ttyUSB0节点编程即可。 2、协议同上一节 cmd data_lenght data0 … datax checksum 1、获取版本…