《深入Linux内核架构》第2章 进程管理和调度 (4)

目录

2.6 CFS调度类

2.6.1 数据结构

2.6.2 CFS操作

2.6.3 队列操作

2.6.4 选择下一个进程

2.6.5 处理周期性调度器

2.6.6 唤醒抢占


2.6 CFS调度类

即完全公平调度类,用于调度普通进程。

2.6.1 数据结构

struct sched_class fair_sched_class = {.next = &idle_sched_class,     连接其他调度器类.enqueue_task = enqueue_task_fair, 将进程se插入到红黑树.dequeue_task = dequeue_task_fair,.yield_task = yield_task_fair,.check_preempt_curr = check_preempt_wakeup,.pick_next_task = pick_next_task_fair,    从红黑树中选择下一个运行的进程.put_prev_task = put_prev_task_fair,.set_next_task = set_next_task_fair,#ifdef CONFIG_SMP.balance = balance_fair,.select_task_rq = select_task_rq_fair,.migrate_task_rq = migrate_task_rq_fair,.rq_online = rq_online_fair,.rq_offline = rq_offline_fair,.set_cpus_allowed = set_cpus_allowed_common,#endif.task_tick = task_tick_fair,     由周期性调度器来调用.update_curr = update_curr_fair,}

CPU的就绪队列,每个CPU都有一个该结构

struct rq {struct cfs_rq     cfs;    CFS调度类的运行队列struct rt_rq      rt;     RT调度类的运行队列}//CFS运行队列
struct cfs_rq {struct load_weight load;     该队列进程的权重总和unsigned int nr_running;     该队列就绪进程数u64 exec_clock;             该队列总共占用的cpu时间u64 min_vruntime;           该队列进程中最小的vruntimestruct sched_entity *curr;  当前正执行进程的调度实体struct rb_root tasks_timeline; 红黑树struct rb_node *rb_leftmost;   因为经常访问,用于缓存红黑树最左节点。};

struct cfs_rq中min_vruntime作用:

        如果一个进程sleep太久,则它的vruntime很小。

        如果进程se->vruntime太小,则:

                se->vruntime = CFS->min_vruntime

2.6.2 CFS操作

enqueue_entity()、dequeue_entity()、task_tick()都会调用update_curr()

更新各种时间,统计量
void update_curr(struct cfs_rq *cfs_rq) {struct sched_entity *curr = cfs_rq->curr;u64 now = rq_clock_task(rq_of(cfs_rq));u64 delta_exec;delta_exec = now - curr->exec_start;   //delta_exec:进程此次调度的执行时间curr->exec_start = now;curr->sum_exec_runtime += delta_exec;     当前进程累计运行时间delta_exec_weighted = calc_delta_fair(delta_exec, curr);  weighted方式计算如下图curr->vruntime += delta_exec_weighted;     更新当前进程vruntimeupdate_min_vruntime(cfs_rq);             更新cfs队列的min_vruntime}

nice值越大,prio优先级越高,查看prio_to_weight数组可知weight越大,根据上面公式可知,delta_exec_weighted越小,这样进程curr->vruntime增长较慢,值越小,进程se越靠近红黑树左边,越先被调度。

        最终nice越大,越先被调用。

进程休眠时:

        se->vruntime不增长,而就绪队列cfs_rq->min_vruntime会递增,唤醒后会se往红黑树左边靠近,越先被调度。

进程运行时:

        se->vruntime增长,会往红黑树右边靠近,越后被调度。

如此就实现了CFS的公平性。

2.6.3 队列操作

enqueue_task_fair:

        把当前进程加入到CFS就绪队列。

void enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags){update_curr(cfs_rq);         更新统计量place_entity(cfs_rq, se, 0); 更新vruntimeif (se != cfs_rq->curr)__enqueue_entity(cfs_rq, se);}

__enqueue_entity:

        遍历红黑数,比较进程和树上进程的vruntime值,若值小在树的左节点,值大在树的右节点,找到插入位置后,将进程se插入到红黑树。

cfs会调度红黑树最左节点的进程。所以struct cfs_rq会缓存最左节点,即:

struct cfs_rq {struct rb_node     *rb_leftmost;}

如何判断一个进程se是否已经在CPU就绪队列?

struct sched_entity {

        unsigned int on_rq;        答:通过该成员值

}

2.6.4 选择下一个进程

pick_next_task_fair:

        选择下一个执行进程。

static struct task_struct *pick_next_task_fair(struct rq *rq){struct task_struct *p;struct cfs_rq *cfs_rq = &rq->cfs;struct sched_entity *se;if (!cfs_rq->nr_running) 该CFS队列没有进程return NULL;se = pick_next_entity(cfs_rq); 取出红黑树最左节点对应进程的se,实现如下set_next_entity(cfs_rq, se); 从红黑树中删除选中的进程se,并更新统计}pick_next_entity -> __pick_first_entitystruct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq){struct rb_node *left = cfs_rq->rb_leftmost;     缓存的红黑树最左节点return rb_entry(left, struct sched_entity, run_node);//使用container_of宏,根据rb_node,得到对应se}

2.6.5 处理周期性调度器

每次时钟中断会调用task_tick_fair()

void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued){struct cfs_rq *cfs_rq;for_each_sched_entity(&curr->se) {cfs_rq = cfs_rq_of(se);entity_tick(cfs_rq, se, queued); //如下图}}

update_curr():周期更新统计量。

check_preempt_tick:

        如果进程运行时间大于期望时间间隔, 调用resched_task来设置当前进程的TIF_NEED_RESCHED标志,让出CPU。

设置TIF_NEED_RESCHED 标志后,等到抢占时机时,检查标志,并实施抢占操作。

CFS调度类fair_sched_class,可用的policy:

        SCHED_NORMAL

        SCHED_BATCH

        SCHED_ILDE

RT调度类rt_sched_class,可用的policy:

        SCHED_RR

        SCHED_FHFO

2.6.6 唤醒抢占

当do_fork()新进程,会调用wake_up_new_task唤醒新进程,然后调用check_preempt_curr。

void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags){const struct sched_class *class;rq->curr->sched_class->check_preempt_curr(rq, p, flags);}

CFS中check_preempt_curr定义如下:

const struct sched_class fair_sched_class = {.check_preempt_curr = check_preempt_wakeup,}

check_preempt_wakeup:

        检查当前新进程是否需要被抢占,以唤醒更高优先级的进程运行。

若需要让出CPU,让高优先级进程先运行,则调用resched_task:

        resched_task设置当前进程TIF_NEED_RESCHED标记。

应确保se被抢占前至少运行时间大于最小时间限额,避免频繁切换。

注意:设置完进程的TIF_NEED_RESCHED标志不代表当前进程立马被切换出去,而是等到抢占时机点,再来检查TIF_NEED_RESCHED标记标志,执行切换进程工作。

TIF_NEED_RESCHED:存储在进程thread_info的flag成员中。

抢占时机点:

        1. 中断返回内核态时。

        2. 退出临界区,如释放自旋锁。

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

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

相关文章

Restormer: Efficient Transformer for High-Resolution Image Restoration

Abstract 由于卷积神经网络(CNN)在从大规模数据中学习可概括的图像先验方面表现良好,因此这些模型已广泛应用于图像恢复和相关任务。最近,另一类神经架构 Transformer 在自然语言和高级视觉任务上表现出了显着的性能提升。虽然 T…

【安全类书籍-2】Web渗透测试:使用Kali Linux

目录 内容简介 作用 下载地址 内容简介 书籍的主要内容是指导读者如何运用Kali Linux这一专业的渗透测试平台对Web应用程序进行全面的安全测试。作者们从攻击者的视角出发,详细阐述了渗透测试的基本概念和技术,以及如何配置Kali Linux以适应渗透测试需求。书中不仅教授读者…

vulnhub-----SickOS靶机

文章目录 1.信息收集2.curl命令反弹shell提权利用POC 1.信息收集 ┌──(root㉿kali)-[~/kali/vulnhub/sockos] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:10:3c:9b, IPv4: 10.10.10.10 Starting arp-scan 1.9.8 with 256…

邮件客户端 Thunderbird 简单配置

1. 基本情况介绍 原来使用的邮箱客户端是 Office 365 自带的 Outlook 365切换原因:新装电脑,发现原 Outlook 中的账号信息无法迁移,需要耗费大量时间手动配置邮箱使用的邮箱:微软 O365 邮箱、qq 邮箱、163 邮箱、公司私有邮箱 …

clickhouse介绍

ClickHouse 是一个开源的分布式列式数据库管理系统(DBMS),是专门针对 OLAP(联机分析处理)场景设计的。它由俄罗斯的 Yandex 公司开发,具有高性能、可扩展性强、支持 SQL 查询等特点。 ClickHouse 的主要特点包括: 列…

北斗卫星引领农机春耕新时代

北斗卫星引领农机春耕新时代 随着现代科技的快速发展,北斗卫星成为了农业领域不可或缺的利器。在农机自动驾驶系统的引领下,农机正逐渐实现自主操作,为农民节省了大量的时间和精力,并最大限度地提高了农作物的产量和质量。 北斗…

GEE高阶案例——利用eemont实现 GEE STAC 中任意栅格数据RASTER 的 STAC 信息

教程中主要是利用eemont包实现检查 GEE STAC 中任意 RASTER 数据集的 STAC 信息 简介 遥感影像是利用航空飞机、卫星等远距离无人机获取地球表面信息的技术,可以提供丰富的波段和属性信息。下面将详细介绍如何查看遥感影像的波段和属性信息。 1. 查看波段信息: 遥感影像通…

python之bootstrap样式

BootStrap <!DOCTYPE html> <html lang"en"> <head><!--注释--><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"static/plugins/bootstrap-3.4.1/css/bootstrap.css…

MySQL | 内置函数

目录 1. 日期函数 2. 字符串函数 3. 数学函数 4. 其他函数 4.1. USER()查询当前用户 4.2. MD5(STR)对一个字符串进行md5摘要 4.3. DATABASE()显示当前正在使用的数据库 4.4. PASSWORD()函数&#xff0c;MySQL使用该函数对用户进行加密 4.5. IFNULL(VAL1, VAL2)如果VAL1…

window下安装并使用nvm(含卸载node、卸载nvm、全局安装npm)

window下安装并使用nvm&#xff08;含卸载node、卸载nvm、全局安装npm&#xff09; 一、卸载node二、安装nvm三、配置路径和下载源四、使用nvm安装node五、nvm常用命令六、卸载nvm七、全局安装npm、cnpm八、遇到的问题 nvm 全名 node.js version management&#xff0c;顾名思义…

Vivado中的五种仿真模式比较

Vivado中的五种仿真模式 在数字电路设计过程中&#xff0c;通常涵盖三个主要阶段&#xff1a;源代码编写、综合处理以及电路的实现&#xff0c;相应地&#xff0c;电路仿真的应用也与这些阶段紧密相关。根据不同设计阶段的需求&#xff0c;仿真可以被划分为RTL行为级仿真、综合…

练习4-权重衰减(李沐函数简要解析)

环境:练习1的环境 代码详解 0.导入库 import torch from torch import nn from d2l import torch as d2l1.初始化数据 这里初始化出train_iter test_iter 可以查一下之前的获取Fashion数据集后的数据格式与此对应 n_train, n_test, num_inputs, batch_size 20, 100, 200, …

Redis的安全配置有哪些建议?如何防止未授权访问?Redis的监控与告警策略是怎样的?如何及时发现并解决潜在问题?

Redis的安全配置有哪些建议&#xff1f;如何防止未授权访问&#xff1f; Redis的安全配置对于保护系统免受未授权访问和其他潜在风险至关重要。以下是一些建议的安全配置措施&#xff1a; 设置密码并禁用不安全的命令&#xff1a; 为Redis实例设置一个强密码&#xff0c;确保密…

鸿蒙原生应用开发-ArkTS语言基础类库多线程CPU密集型任务TaskPool

CPU密集型任务是指需要占用系统资源处理大量计算能力的任务&#xff0c;需要长时间运行&#xff0c;这段时间会阻塞线程其它事件的处理&#xff0c;不适宜放在主线程进行。例如图像处理、视频编码、数据分析等。 基于多线程并发机制处理CPU密集型任务可以提高CPU利用率&#xf…

三款.NET代码混淆工具比较分析:ConfuserEx、Obfuscar和Ipa Guard

随着.NET应用程序的广泛应用&#xff0c;保护知识产权和防止逆向工程的需求逐渐增长。本文将详细介绍三款知名的.NET代码混淆工具&#xff1a;ConfuserEx、Obfuscar和Ipa Guard&#xff0c;帮助读者全面了解其功能特点和应用场景。 一、ConfuserEx ConfuserEx是一个.NET代码混…

文件太大无法拷贝到u盘怎么办?可能是这个隐藏原因~

有时候我们新买的U盘&#xff0c;明明有64G的存储空间&#xff0c;怎么一个4.5G的视频想保存到U盘里会提示“文件太大”无法保存呢&#xff1f; 常见的U盘格式有FAT、FAT32、NTFS等&#xff0c;其中FAT32不支持存储单个文件体积大于4G的文件。下面教大家如何对U盘格式进行检测呢…

二开飞机机器人群发,实现自动给多个频道发送消息

频道1 频道2 二开代码部分&#xff1a; const CChatIdListprocess.env.CHANNEL_CHAT_ID_LIST; var channelChatIdArray CChatIdList.split(,);channelChatIdArray.forEach(function(item) {console.log(item); // 这里可以替换为您需要对数组中每个值进行的操作bot.sendM…

个人开发App成功上架手机应用市场的关键步骤

目录 1. 苹果审核和APP备案 2. APP上架操作步骤 3. 审核和发布 4. 上线工作 总结 参考资料 在当前移动应用市场竞争激烈的背景下&#xff0c;个人开发App如何成功上架成为开发者们必须面对的重要任务。本文将重点介绍自建App上架至手机应用市场的流程&#xff0c;包括苹果…

HDOJ 2078

复习时间 Problem Description 为了能过个好年&#xff0c;xhd开始复习了&#xff0c;于是每天晚上背着书往教室跑。xhd复习有个习惯&#xff0c;在复习完一门课后&#xff0c;他总是挑一门更简单的课进行复习&#xff0c;而他复习这门课的效率为两门课的难度差的平方,而复习第…

String类型详解

1. Java为何要创造String类 在C语言中,是没有String这个类型的,通常使用字符数组中存放一个个字符,再加上最后一个\0来表示/存放一个字符串.也可以使用一个字符指针指向字符串的首元素,直到遇到\0停止,再加上C语言头文件string.h中封装的函数,对于字符串的操作已经够用了. Java…