《深入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 邮箱、公司私有邮箱 …

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

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

MySQL | 内置函数

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

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

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

Vivado中的五种仿真模式比较

Vivado中的五种仿真模式 在数字电路设计过程中,通常涵盖三个主要阶段:源代码编写、综合处理以及电路的实现,相应地,电路仿真的应用也与这些阶段紧密相关。根据不同设计阶段的需求,仿真可以被划分为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, …

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

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

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

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

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

频道1 频道2 二开代码部分: 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. 上线工作 总结 参考资料 在当前移动应用市场竞争激烈的背景下,个人开发App如何成功上架成为开发者们必须面对的重要任务。本文将重点介绍自建App上架至手机应用市场的流程,包括苹果…

String类型详解

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

学完Python的7大就业方向,哪个赚钱最多?

“ 我想学Python,但是学完Python后都能干啥 ?” “ 现在学Python,哪个方向最简单?哪个方向最吃香 ?” “ …… ” 相信不少Python的初学者,都会遇到上面的这些问题。大家都知道Python很吃香,薪资…

进程管理与计划任务管理

进程管理 1、查看进程 静态 ps -auxps -elf 动态 top pgrep 查看特定条件的进程 pgrep -l “log” pgrep -l "ssh"pgrep -l -U redhat pstree 查看进程树 pstree -aup 所有用户、进程id\详细信息pstree -ap redhat 查看redhat用户的进程 任务调…

如何实现在固定位置的鼠标连点

鼠大侠的鼠标连点功能是免费的 浏览器搜索下载鼠大侠,指定连点间隔和启动快捷键 点击设置,指定点击位置

Linux 常用操作命令大全

目录 一、命令大集合 1.1 whereis 1.2 which 1.3 sudo 1.4 grep 1.5 free 1.6 top 动态显示进程的状态 1.7 ps 静态显示进程信息 1.8 df 1.9 iostat 看IO性能状态 1.10 yum安装插件命令 1.11 rpm 1.12 scp远程拷贝 1.13 uname 二、linux网络命令 2.1 centos7 防火…

SpringCloudAlibaba Nacos配置及应用

Nacos搭建及配置 nacos本机服务搭建 windows上搭建单机nacos: Releases alibaba/nacos GitHub 下载安装包 下载本地,解压,直接运行(保证安装包的绝度路径只有英文字符,有中文会导致运行失败)&#xff…