一文搞懂core-scheduling核心机制
cookie的原理借助于unsigned long型,和refcount_t引用计数器。
32位 | 64位 | |
---|---|---|
char * | 4字节 | 8字节 |
unsigned long | 4字节 | 8字节 |
数据结构修改
首先看看实现core scheduling功能对数据结构有哪些修改
task_struct
struct task_struct{struct rb_node core_node;unsigned long core_cookie;unsigned int core_occupation;
}
sched_statistics
struct sched_statistics{u64 core_forceidle_sum;
}
sched_core_cookie
cookie本质就是一个内核引用计数器refcount_t成员构成的struct结构体。然后task_struct中保存的core_cookie是unsigned long型数据,刚好能存放指针变量值,就是存放的该结构体的内存地址。
使用alloc分配出来的sched_core_cookie结构体的address内存地址作为一个task的cookie值,cookie 类型是unsigned long的指针。
/*新增*/
struct sched_core_cookie{refcount_t refcnt;
}
rq
rq中增加了有关core sched的开关等信息。
struct rq {//...省略
#ifdef CONFIG_SCHED_CORE/* per rq */struct rq *core;struct task_struct *core_pick;unsigned int core_enabled;unsigned int core_sched_seq;struct rb_root core_tree; /*可以使用同一个core的都要加入红黑树*//* shared state -- careful with sched_core_cpu_deactivate() */unsigned int core_task_seq;unsigned int core_pick_seq;unsigned long core_cookie;unsigned int core_forceidle_count;unsigned int core_forceidle_seq;unsigned int core_forceidle_occupation;u64 core_forceidle_start;
#endif
}
这部分初始化
#ifdef CONFIG_SCHED_CORErq->core = rq;rq->core_pick = NULL;rq->core_enabled = 0;rq->core_tree = RB_ROOT;rq->core_forceidle_count = 0;rq->core_forceidle_occupation = 0;rq->core_forceidle_start = 0;rq->core_cookie = 0UL;
#endif
cfs_rq
struct cfs_rq{//...省略代码#ifdef CONFIG_SCHED_COREunsigned int forceidle_seq;u64 min_vruntime_fi;
#endif
}
cookie
用户态程序通过prctl系统调用来操作相关进程的cookie动作。
prctl接口
prctl系统调用接口中新增有关PR_SCHED_CORE的操作处理函数。
SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,unsigned long, arg4, unsigned long, arg5)
{...
#ifdef CONFIG_SCHED_COREcase PR_SCHED_CORE:error = sched_core_share_pid(arg2, arg3, arg4, arg5);break;
#endif
}
int sched_core_share_pid(unsigned int cmd, pid_t pid, enum pid_type type,unsigned long uaddr)
{unsigned long cookie = 0, id = 0;struct task_struct *task, *p;struct pid *grp;int err = 0;//...省略rcu_read_lock();if (pid == 0) {task = current; /*pid为0,则是设置进程本身*/} else {task = find_task_by_vpid(pid); /*根据pid查找进程PCB*/if (!task) {rcu_read_unlock();return -ESRCH;}}get_task_struct(task); /*该函数就是为了给task_struct引用符计数+1,防止中断处理中程序被kill掉访问非法PCB指针*/rcu_read_unlock();/* 检查进程是否有权限修改指定的进程* Check if this process has the right to modify the specified* process. Use the regular "ptrace_may_access()" checks.*/if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) {err = -EPERM;goto out;}switch (cmd) {case PR_SCHED_CORE_GET: if (type != PIDTYPE_PID || uaddr & 7) {err = -EINVAL;goto out;}cookie = sched_core_clone_cookie(task); /*获取task任务的cookie值*/if (cookie) {/* XXX improve ? */ptr_to_hashval((void *)cookie, &id);}err = put_user(id, (u64 __user *)uaddr);goto out;case PR_SCHED_CORE_CREATE:cookie = sched_core_alloc_cookie(); /*创建task任务的cookie值*/if (!cookie) {err = -ENOMEM;goto out;}break;case PR_SCHED_CORE_SHARE_TO:cookie = sched_core_clone_cookie(current); /*共享继承指定task任务的cookie值*/break;case PR_SCHED_CORE_SHARE_FROM:if (type != PIDTYPE_PID) {err = -EINVAL;goto out;}cookie = sched_core_clone_cookie(task);__sched_core_set(current, cookie); /*将自身cookie共享给指定的task任务*/goto out;default:err = -EINVAL;goto out;};if (type == PIDTYPE_PID) {__sched_core_set(task, cookie); /*设置任务task的cookie值*/goto out;}read_lock(&tasklist_lock); /*这里是对任务组进行设置,对任务组中每个任务都设置cookie*/grp = task_pid_type(task, type);do_each_pid_thread(grp, type, p) {if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) {err = -EPERM;goto out_tasklist;goto out_tasklist;}} while_each_pid_thread(grp, type, p);do_each_pid_thread(grp, type, p) {__sched_core_set(p, cookie);} while_each_pid_thread(grp, type, p);
out_tasklist:read_unlock(&tasklist_lock);out:sched_core_put_cookie(cookie); /*cookie指针计数器减1,并检查是否为0,没有人用则需要释放*/put_task_struct(task); /*检查task指针技术减1*/return err;
}
该函数中,out出口时为何需要对cookie进行put,对task进行put?
- 对task进行put是因为调用了get_task_struct(task)函数,该函数中会对task引用计数加1,所以在sched_core_share_pid()函数末尾需要对task指针引用计数减1
- 对cookie计数减1,是因为在get_cookie,clone_cookie,allock_cookie等函数中对cookie的引用计数加了1,然后再**__sched_core_set函数中又调用get_cookie,又再次对cookie的计数加了1,一共加了两次,所以函数末尾需要相应的对cookie计数减1并检查是否为0(__sched_core_set**函数中也有一次减1操作,不过是对old_cookie的操作)。所以最终cookie的引用次数整体还是加了1的
创建cookie
何时需要创建cookie?是每个进程都有一个cookie么?cookie值保存在哪里?
static unsigned long sched_core_alloc_cookie(void)
{struct sched_core_cookie *ck = kmalloc(sizeof(*ck), GFP_KERNEL);if (!ck)return 0;refcount_set(&ck->refcnt, 1); /*cookie的计数器加1*/sched_core_get(); /*enable core sched功能,就是打开开关标志*/return (unsigned long)ck;
}
获取cookie
static unsigned long sched_core_get_cookie(unsigned long cookie)
{struct sched_core_cookie *ptr = (void *)cookie;if (ptr)refcount_inc(&ptr->refcnt);return cookie;
}
入参:某个task_struct的cookie值,p->core_cookie; 类型unsigned long存放的其实是指针,该指针指向结构体sched_core_cookie计数器。
get_cookie的操作主要就是对cookie中的refcnt计数器加1。
共享cookie
task任务共享当前current任务的cookie
cookie = sched_core_clone_cookie(current);
__sched_set_core(task, cookie);
static unsigned long sched_core_clone_cookie(struct task_struct *p)
{unsigned long cookie, flags;raw_spin_lock_irqsave(&p->pi_lock, flags);cookie = sched_core_get_cookie(p->core_cookie); //获取指定进程的core_cookie值raw_spin_unlock_irqrestore(&p->pi_lock, flags);return cookie;
}
分享cookie
分享当前current任务的cookie给指定任务task。
cookie = sched_core_clone_cookie(task);
__sched_core_set(current, cookie);
清除cookie
static void sched_core_put_cookie(unsigned long cookie)
{struct sched_core_cookie *ptr = (void *)cookie;if (ptr && refcount_dec_and_test(&ptr->refcnt)) {kfree(ptr);sched_core_put();}
}
当清除task_struct时,也要记得清除其中的cookie
void sched_core_free(struct task_struct *p)
{sched_core_put_cookie(p->core_cookie);
}
父子进程cookie关系
在fork系统调用中,copy_process创建新进程的时候,子进程的cookie值继承父进程的cookie值。
void sched_core_fork(struct task_struct *p)
{RB_CLEAR_NODE(&p->core_node); /*core_node红黑树节点清空*/p->core_cookie = sched_core_clone_cookie(current); /*子进程cookie = 父进程cookie*/
}
周期性调度器
scheduler_tick()周期性调度器中也会涉及到core sched的操作。
相关文章:
一文搞懂core-scheduling核心机制
cookie的原理借助于unsigned long型,和refcount_t引用计数器。 32位64位char *4字节8字节unsigned long4字节8字节 数据结构修改 首先看看实现core scheduling功能对数据结构有哪些修改 task_struct struct task_struct{struct rb_node core_node;unsigned long…...
IP地址在金融行业有哪些应用?
中国加入WTO以来经济得到迅速发展,金融行业随着经济发展体系越来越完善。随着西方金融公司和理念的加入中国金融行业开始多样化发展。金融行业在快速发展的同时也引发了许多弊端。如何维护挖掘客户更大需求?如何获取更多优质客户?如何提升网络…...
GT-suite v2016解决许可证过期问题(附新版liscense下载地址)
安装GT-suite v2016时遇到了如图报错的问题。当时的报错找不到了,下图是贴吧相同问题的报错图。 为了解决问题,先根据某网友的如下答复操作: 添加环境变量后仍然有相同报错。 看来需要寻找其他方法。 再尝试着卸载GT-suite v2016,…...
小红书商业笔记与普通笔记区别是什么?小红书笔记有哪几种
主攻单一平台,如何迅速打造爆文。针对软文发布类别的选择,小红书商业笔记与普通笔记区别究竟是什么,今天为大家带来的详细分析,告诉你该如何用最少的成本,做出“爆文”。1、小红书的笔记类型我们都知道,小红…...
DataWhale-统计学习方法打卡Task01
学习教材《统计学习方法(第二版)》李航 统计学习方法(第2版) by...李航 (z-lib.org).pdf https://www.aliyundrive.com/s/maJZ6M9hrTe 点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无…...
Java面试——Spring 事务
目录 1.什么是Spring 事务 2.Spring 事务的开启方式 3.Spring事务的实现方式/原理 4.事务传播机制 5.事务隔离级别 6.事务失效的原因 1.什么是Spring 事务 事务在逻辑上是一组操作,要么执行,要不都不执行。 如下: Begin; insert into…...
Python语言零基础入门教程(十九)
Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误。你可以使用该功能来调试python程序。 1、异常处理 2、断言(Assertions) python标准异常 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生&…...
重生之我是赏金猎人-SRC漏洞挖掘(一)-某SRC测试系统无脑Getshell
0x01 前言 https://github.com/J0o1ey/BountyHunterInChina 欢迎大佬们点个star 0x02 资产收集到脆弱系统 在某src挖掘过程中,本人通过ssl证书对域名资产进行了收集,通过计算域名对应ip段的权重 整理出其C段资产,进行了批量目录扫描 查看…...
Sciter 结合 PReact 实现组件公共逻辑抽离
Sciter 结合 PReact 实现组件公共逻辑抽离 下面例子是获取鼠标移动位置,将这部分逻辑进行抽离 一、使用高阶组件抽离公共逻辑 import {Component } from ./preact.js; export const HOCFactory = (Component) => {class HOC...
OpenTracing协议规范链接
一、官网链接 OpenTracing specificationhttps://opentracing.io/specification/不过目前OpenTracing项目已归档,不再维护。需要参考OpenTelemetry官网链接 Migrating from OpenTracing | OpenTelemetryBackward compatibility with OpenTracing has been a prior…...
金三银四面试必看,自动化测试如何解决日志问题
前言 前几天在员群里,有同学问了一个自动化测试实践中遇到的问题: 持续集成的自动化用例很多,测试环境日志level为debug,日志量大概40G/每天,定位问题时日志查询很慢,该怎么解决? 这个问题可…...
微信怎么开小店?【企业商家微信开店】
企业商家入局微信做营销已经是经营规划中必须做的一件事了,对于企业商家来说,最简单直接的方式就是开一个微信小店,然后通过自己宣传推广来在微信小店中成商品。那么企业商家在微信怎么开小店呢?下面内容分享给想在微信开店的企业…...
Java 中FastJson的使用【吃透FastJson】
如果不了解JSON格式,建议先看下:JSON数据格式【学习记录】 JSON序列化、反序列化JavaBean的框架有很多,最常见的Jackson、阿里巴巴开源的FastJson、谷歌的GSON、apache提供的json-lib等,下面我们主要来熟悉一下:Java语…...
Redis5.0集群搭建
Redis集群教程 此文重在介绍 Redis5.0 三主三从集群安装,无复杂难懂的概念,若想深入了解集群原理请参考Redis集群规范。 Redis集群介绍 Redis Cluster 提供一种 Redis 安装方式:数据自动在多个 Redis 节点间分片。 Redis Cluster 提供一定…...
继企业级信息系统开发学习1.1 —— Spring配置文件管理Bean
骑士救美计划采用构造方法注入属性值1、创建救美任务类2、创建救美骑士类2、创建救美骑士类3、创建旧救美骑士测试类3、配置救美骑士Bean5、创建新救美骑士测试类采用构造方法注入属性值 1、创建救美任务类 在net.huawei.spring.day01包里创建RescueDamselQuest类 Rescue Da…...
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
首先浏览器发起 HTTP 请求,像早期的时候只会请求一些静态资源,这时候需要一个服务器来处理 HTTP 请求,并且将相应的静态资源返回。 这个服务器叫 HTTP 服务器。 简单点说就是解析请求,然后得知需要服务器上面哪个文件夹下哪个名字…...
eBPF 进阶: 内核新特性进展一览
Linux 内核在 2022 年主要发布了 5.16-5.19 以及 6.0 和 6.1 这几个版本,每个版本都为 eBPF 引入了大量的新特性。本文将对这些新特性进行一点简要的介绍,更详细的资料请参考对应的链接信息。总体而言,eBPF 在内核中依然是最活跃的模块之一&a…...
2.输入子系统学习-multi-touch-protocol-2023.02
Documentation/input/multi-touch-protocol.txt(百度翻译) Multi-touch (MT) Protocol ------------------------- Copyright (C) 2009-2010 Henrik Rydberg <rydbergeuromail.se> 一、Introduction ------------ In order to utilize t…...
【靶机】vulnhub靶机pylington
靶机下载地址 Pylington: 1 ~ VulnHub kali ip:192.168.174.128 靶机ip:192.168.174.146 arp-scan -l发现靶机ip是192.168.174.146 进行靶机的端口扫描,这里使用的是nmap的gui 可以发现开放了21和80端口,80端口扫描到了robot…...
【大数据】大数据学习路线
职位选择 首先明确一点:大数据涉及的知识面广度还是有的,需要学习的组件繁多,想要每一项精通几乎不可能,所以企业在招聘的时候会进行细分,基于某个方向进行招聘,比如关键字,数据仓库工程师、数…...
【Python爬虫案例教学】采集某网站壁纸,实现壁纸自由
前言 (。・∀・)ノ゙嗨 大家好,这里是小圆 现在开始每天都给大家 分享些关于python爬虫的案例教学 从最简单的开始 — 采集图片壁纸 今天就来扒拉这个优质的壁纸网站~ 网址 👇 顺便瞧一眼 这里的…...
波卡2022年第四季度报告
本文将介绍Messari最新发布的波卡Polkadot 2022年第四季度报告内容。 1 Messari已经发布关于波卡Polkadot最新的报告:显示了2022年第四季度的日活账户增加了64%,新用户增长49%。 2 Messari指出,波卡中继链在2022第四季度的环比增长令人印象…...
第一章:初始化react项目+antd+less
初始化react项目 我们首先使用react脚手架创建一个项目 Ant Design less creact-react-app中文文档 creact-react-app demo生产环境打包运行 当我们执行了 npm run build 打包后直接访问index.html 看效果白屏 这时候就需要安装一个serve包 npm install -g serve当我们安…...
图的基本概念
1、图的概念 G(V,E) 图G由节点集合VV(G)和边集合EE(G)组成,其中V为非空有限集合。 集合V中的节点(node)用红色标出,通过集合E中黑色的边(edge)连接。 G的边:E中的每个顶点对&#x…...
MySQL必会四大函数-窗口函数
在了解窗口函数之前,我们必须了解聚合函数。常见的聚合函数,包括 AVG、COUNT、MAX、MIN、SUM 以及 GROUP_CONCAT,常和GROUP BY 函数一起使用。聚合函数的作用就是对一组数据行进行汇总计算,并且返回单个分析结果。 窗口函数和聚合…...
各CCF期刊点评网站/学术论坛的信息汇总及个人评价
CCF中文期刊投稿选择之篇章一:各CCF期刊点评网站/学术论坛的信息汇总及个人评价中文科技期刊A类(EI检索)中文期刊投稿点评网站整理1.小木虫学术论坛2. Letpub3. Justscience4. 发表记5. 会伴(Conference Partner)6. ijouranl7. 掌桥科研这是以…...
深度解析 JavaScript 严格模式:利弊长远的考量
前言 ECMAScript 5首次引入严格模式的概念。严格模式用于选择以更严格的条件检查JavaScript代码错误,可以应用到全局,也可以应用到函数内部。 严格模式的好处是可以提早发现错误,因此可以捕获某些 ECMAScript 问题导致的编程错误。 理解严格…...
Vue.js 循环语句
Vue.js 循环语句 在Vue开发中,for循环是我们最常遇见的场景之一,我们知道常见的遍历方式有for循环,for of、forEach、for in.虽然在开发过程中,这几种方式基本上可以满足我们大多数的场景,但是你真的知道他们之间的区…...
家政服务小程序实战教程12-详情页
我们的家政服务小程序已经完成了首页和分类展示页面的开发,接下来就需要开发详情页了。在详情页里我们展示我们的各项服务内容,让用户可以了解每项家政服务可以提供的内容。 低码开发不像传统开发,如果开发详情页需要考虑每个字段的类型&…...
十四、平衡二叉树
1、看一个案例(说明二叉排序树可能的问题) 给你一个数列{1,2,3,4,5,6},要求创建一棵二叉排序树(BST),并分析问题所在。 上面二叉排序树存在问题分析: 左子树全部为空,从形式上看&…...
给网站权限/石家庄网站建设方案推广
今天突然发现document.onclick这个事件没有效果了,本来删除需要弹出提示框的,但是都给直接删除掉了。 而在别的电脑上就是好使的,能弹出提示框。IE8,IE9都是无效的。 经百度发现,原来是QQ惹的祸。莫名其妙的装上这个插…...
淮安建立公司网站流程/营销案例
NDFI是什么? NDFI被称为归一化退化指数。可以用来表达森林植被的退化程度和森林的健康程度。 NDFI最开始发表的文章是(Combining spectral and spatial information to map canopy damage from selective logging and forest fires)。该指数…...
土特产 网站源码/什么网站百度收录快
01 服务器虚拟化介绍 02 VMware组件介绍 03 ESXi介绍 04 vCenter Server介绍 05 VMware虚拟机及虚拟机管理介绍 06 Vmware vMotion及Storage vMotion 07 Vmware 可用性及可扩展性介绍...
用Axure做的网站原型百度云/十大小说网站排名
人们会因为偶尔的小毛病而异常难受,而对大多数平常日子里的活蹦乱跳却毫无知觉。现代科学发现佛陀“放下身外之物”的观点也不够全面,因为确实有少数的身外之物能够给我们带来持续的幸福,值得我们追求。(1)良好的人际关…...
企业建网站报价/百度推广关键词技巧定价
中关村在线消息:华为今日发布了2019年上半年业绩:上半年销售收入4013亿元,同比增长23.2%。其中消费者业务2208亿元,占比55%。华为今年上半年智能手机发货量(含荣耀)达到1.18亿台,同比增长24%。华为董事长梁华表示&…...
网站都有备案号吗/游戏广告联盟平台
查询表内容: select * from stu; (stu是一张表) 显示表结构: desc stu;...