Linux相关概念和易错知识点(11)(进程调度、Linux内核链表)

【Linux 内核源码分析】进程调度 -CFS 调度器 在CFS(Completely Fair Scheduler)调度器中,任务的权重值由其nice值决定,通过对比不同任务的权重值,CFS会分配合理的CPU时间片给每个任务。这种方式实现了一种类似于多态的效果,即不同的任务可以使用不同的调度算法,而调度器的函数指针则根据具体的调度器类型来指向对应的函数。通过这种方式,Linux 内核可以根据任务的调度器类型来调用相应的调度函数,实现了灵活的调度策略,并且能够方便地扩展和切换不同的调度器。高优先级的任务会获得更多的虚拟运行时间,在排序和选择调度时更容易被选中。 阅读详情

目录

1.Linux调度算法

(1)queue

(2)runqueue

(3)调度算法

(4)bitmap存在的意义

2.Linux内核链表


1.Linux调度算法

上篇文章我粗略讲过queue[140]的结构,根据哈希表,我们可以将40个不同优先级的进程借助哈希桶链入queue[140]中。调度器会根据queue的下标来进行调度。但这个具体的调度过程是怎样的呢?以及runqueue和queue[140]的关系是什么?我们需要更深入了解

(1)queue

PCB* queue[140]只是一个成员变量,它存在于另一个结构体queue中。

我们可以用数组queue[140]和结构体queue来区分它们。

当有PCB从里面链入或者链出时,nr_active和bitmap都会相应更新

我们可以知道,一个结构体queue就能将进程按优先级处理完,但进程的处理是动态的过程,我们要知道他是怎么流转起来的。这就需要知道runqueue的结构了。

(2)runqueue

runqueue是以结构体queue为基本结构,为满足动态调度而建立起来的。其中active活跃指针指向的array里面的PCB* queue[140]就是CPU正在调度的PCB队列,换句话说,调度器只会从active指向的PCB队列中调度进程。这样实现为什么呢?那另一个array干什么呢?我们需要设想,如果在CPU执行的过程中由新的进程加入进来怎么办?同时,CPU要如何在既保证优先级又保证较为公平的调度呢?

(3)调度算法

①新增:当有新的进程加入runqueue时,它并不会直接加入active指向的队列,而是会链入expired指向的结构体queue里面的PCB* queue[140],链入规则和前面一样,都遵循哈希算法。

②现有的进程:当active指向的队列里的一个进程被执行完一次之后,它并不会被链入到当前active对应的PCB* queue[140]中,而是会和那些新进程一样,链入expired指向的PCB* queue [140]中。

③完成的进程:当有进程在active被执行一次并完成后,就会进入Z+X状态,就不会被链入expired里面的PCB* queue [140]了,等着被父进程读取回收就行了

我们发现,expired对应的PCB* queue [140]对应的PCB*越来越多(nr_active也增大),而active对应的PCB* queue [140]却越来越少(nr_active减小)。当nr_active == 0时,active和expired的指针交换,这个时候我们就发现expired(原来的active)空了,active(原来的expired)满了。接下来就继续按上述规则执行(active取,放回expired,新增放入expired),如此往复,一个动态的调度过程就形成了。

从上述过程我们就能发现整个调度过程既保证了优先级,也保证了公平性,同时新增入的进程也不会和正在执行的进程发生冲突。调用规则保证了每一次循环active里面的每一个PCB都会被执行(nr_active记录PCB*数量,每调用一次就减1,不会遗漏),而按照顺序调用又保证了优先级,即优先级高的先执行,低的后执行。

(4)bitmap存在的意义

runqueue中active、expired、array[2]存在的意义很明确,没有它们就构不成整个调度的流转,上述的过程就是它们存在的意义。对于queue来说,nr_active用于记录PCB*的数量,即active、expired分别指向的结构体里进程的数量,只有当active里面的进程调度完了(nr_active == 0)才会swap两个指针,它明确了每次swap的时机,也保证了调度进程的公平性。

但还有个细节,那就是遍历PCB* queue [140]效率不高,明明数组可以随机访问,但又要保证所有PCB都被访问,所以就有bitmap的出现。通过160位bit我们可以得到140个位置存放PCB的情况,比如假定bitmap[0]是5,根据101B,我们得到PCB* queue[140]的第0位和第2位有进程,其余30位都没有进程,可以直接跳过。每个int我们就可以扫掉32个位置,效率很高。具体操作涉及到位操作,之前也有讲过一些位操作得到1或0的办法,很多,这里我们明白是怎么一回事即可。

总结:这是一个进程饥饿问题(公平与优先级的矛盾),采用双queue来解决问题,使得active永远处于存量竞争状态,随着时间竞争越来越小,再交换指针重复操作,实现公平与优先级共存。整个调度算法框架的时间复杂度控制在O(1),效率很高。

2.Linux内核链表

我们常见的链表无外乎分为带头和不带头、单向还是双向、循环还是不循环。这种链表有个共同特点,就是数据和链绑定在了一起。但在Linux内核中,一个PCB,它有可能既是在queue队列,又有可能在waitqueue,那么我们应该怎么做呢?这就是Linux的内核链表,它将链和数据分离,用位操作来访问,极大增强了数据链接和访问的效率。

但这种链表访问数据很麻烦,因为我们只能得到链表连接点的地址,而其它地方的地址并不好拿,我们要想办法拿到struct的起始地址。思路是&(struct  A*)0->(要查找的成员变量链接点)可以得到偏移量offset(宏),再使用(链接点) - offset得到struct A的起始地址,之后就能正常访问了。难点在C语言,学习过偏移量和宏应该能很快理解。

PCB之间就是用这种链表联系起来的,在不同状态切换的效率上很有优势

Linux进程管理与调度 目录 一、进程描述符 二、进程切换 三、进程创建与终止 四、用户线程,内核线程和轻量级进程 五、三种线程模型和Linux线程实现 六、进程与线程的区别 七、实时线程与实时操作系统 八、进程(线程)调度 一、进程描述符 进程描述符保存了与进程相关的一切信息,其数据类型为task_struct,Linux用双向链表和类似HashMap的散列表来保存所... 阅读详情

相关推荐

内核的进程管理与调度

不同操作系统下,进程管理与调度的实现和机制有很大不同。对于上层应用(特别是跨平台)的开发,进程管理与调度显得不那么重要;但是,对于贴近操作系统的底层开发,就非常有必要了解Linux中进程的管理与调度

XiaoBaWu的博客 1228

Linux系统笔记:内核链表

内核链表是在Linux开发中经常用到的一种存储结构,它比普通的单向链表、双向链表更加强大,更加好用。 一、首先回顾一下单向链表与双向链表 1、单向链表: 单向链表节点结构体: struct link_list { int data;//数据域 struct link_list * next;//指针域 }; 单向循环链表结构如图所示: 2、双向链表 双向链表节点结构体: struct link_list { int data;//数据域 struct link_list * next;//指针域

mbs706的博客 3281

linux内核分析之调度——实时调度算法

linux内核中提供了两种实时调度策略:SCHED_FIFO和SCHED_RR,其中RR是带有时间片的FIFO。这两种调度算法实现的都是静态优先级。内核不为实时进程计算动态优先级。这能保证给定优先级别的实时进程总能抢占优先级比他低得进程。linux的实时调度算法提供了一种软实时工作方式。实时优先级范围从0到MAX_RT_PRIO减一。默认情况下,MAX_RT_PRIO为100,所以默认的实时优先级

bullbat的专栏 9282

linux内核链表最细讲解

由于知道了大小结构体之间的偏移量我们又将小结构体转变成(char*)类型使其一个字节一个字节移动故(char*)_mptr-((size_t)&((TYPE*)0)->MEMBER)是将我们小结构体的地址减去其偏移量得到大结构体变量的首地址,(type*)(char*)_mptr-((size_t)&((TYPE*)0)->MEMBER)之后在将其强转为大结构体指针类型。同理我们第一步将list节点截切出来,即用删除操作令其掉出链表,之后我们将list节点插在head的前面完成了对list节点的移动。

yzw_yy的博客 1698

Linux进程概念(精讲)

文章目录 基本概念 描述进程-PCB task_struct-PCB的一种 task_struct内容分类 查看进程 通过系统目录查看 通过ps命令查看 通过系统调用获取进程的PID和PPID 通过系统调用创建进程- fork初始 fork函数创建子进程 使用if进行分流 Linux进程状态 运行状态-R 浅度睡眠状态-S 深度睡眠状态-D 暂停状态-T 僵尸状态-Z 死亡状态-X 僵尸进程 僵尸进程的危害 孤儿进程 进程优先级 基本概念 查看系统进程 PRI与NI 查

m0_58523831的博客 24万+

2024年最全scrapy+scrapyd+gerapy 爬虫调度框架,字节跳动面试时间

scrapyd是一个用于部署和运行scrapy爬虫的程序,它允许你通过JSON API来部署爬虫项目和控制爬虫运行,scrapyd是一个守护进程,监听爬虫的运行和请求,然后启动进程来执行它们方便地控制爬虫运行直观地查看爬虫状态实时地查看爬取结果简单地实现项目部署统一地实现主机管理轻松地编写爬虫代码。

2401_84140653的博客 1200

Linux内核--链表结构

与list_for_each不同,list_for_each遍历的是链表节点,而list_for_each_entry遍历的是由链表节点串起来的结构体链表。list_del:删除链表中的entry节点,entry节点的前驱后继指针指向LIST_POSITION1和LIST_POSITION2两个特殊值,这样设置是为了保证不在链表中的节点项不可访问,对LIST_POSITION1和LIST_POSITION2的访问都将引起页故障。list_for_each的加强版,支持遍历过程的节点删除操作,提高安全性。

qq_34888036的博客 1349

hive sql每个用户的累积访问次数

我们有如下的用户访问数据 userId visitDate visitCount u01 2017/1/21 5 u02 2017/1/23 6 u03 2017/1/22 8 u04 2017/1/20 3 u01 2017/1/23 6 u01 2017/2/21 8 U02 2017/1/23 6 U01 2017/2/22 4 要求使用SQL...

weixin_39150719的博客 3481

【Linux】详细解析Linux内核链表

LIST_POISON1 和 LIST_POISON2 是 Linux 内核用来标记已删除链表节点的特殊值。这是内核开发者采用的一种巧妙的防御性编程技术,有助于编写更安全、更健壮的内核代码。list_entry 利用了 C 语言的一个特性:结构体成员的偏移量是固定的。它计算出 struct list_head 成员在整个结构体中的偏移,然后从这个 list_head 指针反推出整个结构体的起始地址。在上面的函数原型中,有这两行代码,他们的含义是什么呢。

W__winter的博客 2017

新手必看:TwinCAT死活扫不到倍福CX5020?别慌,先检查这3个地方(附静态IP配置)

本文详细介绍了TwinCAT软件无法扫描到倍福CX5020控制器的常见问题及解决方案。从网络连通性检查、系统环境配置到静态IP设置,提供了一套完整的排查流程和优化建议,帮助新手快速解决通信问题,确保设备稳定运行。

weixin_27219587的博客 364

浅析图像处理中的名词:Gamma 校正(Gamma变换、Gamma调整)

浅析图像处理中的名词:Gamma 校正(Gamma变换、Gamma调整)

qq_51908382的博客 1万+

Linux内核基础数据结构-双链表

链表概述 链表作为一种基本的数据结构,得益于其简单的结构、优良的性能(双向链表的插入和删除复杂度都是O(1)),被广泛的应用于各种程序设计中。链表一般分为单向链表和双向链表。对于单向链表,其删除和插入的一般复杂度都是O(n),所以,工程上一般很少使用,下面介绍的所有链表都是双向链表。 常见的双向链表数据结构定义如下: struct list_node_xxx{ struct list_node_xxx *prev,*next; //具体的数据,比如一个char数组 char data[100]; };

飞翔de刺猬 1570

【Excel VBA 编程】表格内自动生成进度条

在表格中生成进度条,进度条需要自适应单元格的宽度,根据不同进度区间变换颜色,并且按照进度数据大小显示其长短

wei1019的专栏 1519

Linux相关概念和易错知识点(8)(操作系统、进程属性)

这些任务列表会根据并行的处理方式交给CPU每个核心处理,CPU的每个核心都配有一个调度器,任务列表会先交给调度器,由调度器决策如何并发处理,适时将对应的PCB交给运算器进行处理。包括生活中,上层对我们的管理也是面向对象的思想,他们不需要和我们见面,他们只需要拿到我们的描述信息,一天里干了什么没干什么,再通过传话就可以实现对我们的管理。,每一种硬件都要有自己的驱动程序(操作系统自带或需要自己安装),驱动程序不可或缺,因为不同硬件功能不同,实现不同,迭代速度快,在硬件层面,有文件系统对磁盘数据进行管理,而。

SGlow0708的博客 964

GD32H7系列SRAM优化配置实战指南

本文详细解析了GD32H7系列MCU的SRAM架构,包括ITCM、DTCM、AXI SRAM等关键内存区域的特点与性能差异。通过实战指南,指导开发者如何通过配置寄存器和链接脚本,优化内存布局以提升系统性能,并重点探讨了DMA操作与CPU缓存一致性的解决方案,帮助充分发挥GD32H7的高性能潜力。

weixin_29169899的博客 518

【ComfyUI专栏】ComfyUI 常用工作流下载与分享网址

首先我们来分享第一个网站,Openart 网站,这个网站同时也能提供比较多的其他类型。但是如果希望下载工作流,我们可以访问到如下的这个站点。作为ComfyUI的学习用户来说,我们通常需要借助他山之石来帮助我们快速成长,因此我们需要找到能够分享和下载的网址。,当前网站是综合性网站,在网站中可以下载各种不同的类型,其中工作流只是可以下载的非常小的部分。这个网站也可以浏览不同的工作流,这个工作流的地址和访问如下的站点。

技术与管理的平衡木- 7792

【Linux篇】进程状态(僵尸进程,孤儿进程),优先级与调度机制

解析了Linux中进程的多种状态,及优先级机制与调度方法

2301_81290732的博客 2487

通用具身智能仿真平台桃源2.0,三行代码定义任务,数采效率最高提升20倍

木木-具身Xbot具身知识库2025年03月13日 17:40浙江在首个“城市级”大规模仿真平台GRUtopia1.0的基础上,升级后的GRUtopia2.0凭借通用模块化框架、场景资产自动化生成、高效数据采集系统三大革新,进一步向通用化、多样化、易用化迈进。仅通过单一平台、简单代码输入,即可实现仿真环境中机器人灵活训练,提升数据采集效率,为研究者提供了“一站式”具身智能开发解决方案。

具身机器人和通用AI 817

Linux下的进程概念相关知识点整理总结

目录1.认识冯诺依曼系统2.操作系统概念与定位3.深入理解进程概念,了解PCB4.学习进程状态,学会创建进程,掌握僵尸进程和孤儿进程,及其形成原因和危害5.了解进程调度, Linux进程优先级,理解进程竞争性与独立性,理解并行与并发6.理解环境变量,熟悉常见环境变量及相关指令, getenv/setenv函数7.理解C内存空间分配规律,了解进程内存映像和应用程序区别, 认识地址空间。8.选学Linux2.6 kernel, O(1)调度算法架构 1.认识冯诺依曼系统 2.操作系统概念与定位 3.深入理解进程

sakeww的博客 2796

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【Linux系统】进程调度:内核 O(1) 的进程调度算法

本文详解讲解:Linux内核真实的进程调度算法、通过哈希结构+多队列(active/expired)的结构 解决进程优先级排序问题与进程饥饿问题

从不依靠,从不寻找,非常沉默,非常骄傲。 你必须非常努力,才能看起来毫不费力。 1254

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Linux内核进程调度时机和过程

1、调度类型和时机 调度触发有两种类型,进程主动触发的主动调度和被动调度,被动调度又叫抢占式调度。 主动调度:进程主动触发以下情况,然后陷入内核态,最终调用schedule函数,进行调度。 1、当进程发生需要等待IO的系统调用,如read、write。 2、进程主动调用sleep时。 3、进程等待占用信用量或mutex时,注意spin锁不会触发调度,可能在空转。 被动调度:当发生以下情况时会发生被动调度: 1、tick_clock,cpu的时钟中断,一般是10ms一次,也有1ms一次的,取决于cpu的主频,

C/C++Linux、音视频、DPDK 3681

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Linux——进程概念

进程概念精析

2302_81486993的博客 3290

linux内核源码分析进程的管理与调度

linux内核源码分析进程的管理与调度

weixin_52259848的博客 2万+

Linux进程概念及进程调度

本文介绍了进程基本概念,冯诺依曼体系结构,进程状态,进程优先级以及调度算法

weixin_74196019的博客 904

理解并使用Linux内核链表

本文介绍了Linux内核链表的基本概念、定义和操作。内核链表是通过struct list_head实现的双向链表,具有高效的插入、删除和遍历操作。链表的节点通过next和prev指针相连,不直接包含数据,这使得链表可以灵活管理不同类型的数据。内核链表的特点包括高效性、简洁性、模块化和操作与数据分离。

Linux内核研究者 2084

【Linux内核】进程调度

本篇博客将会介绍linux中的进程调度策略

m0_74215144的博客 862
上一篇: Linux相关概念和易错知识点(10)(进程优先级、进程切换)
下一篇: Linux相关概念和易错知识点(12)(命令行参数、环境变量、本地变量)
-SGlow-
博客等级 码龄3年 1513粉丝 118原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值