Linux CFS 调度器 (1):概述
文章目录
- 1. 前言
- 2. CFS 调度器
- 2.1 概述
- 2.2 一些实现细节
- 2.3 运行队列:红黑树
- 2.4 一些特征
- 2.5 调度策略
- 2.6 调度器类别
- 2.7 扩展:组调度
- 3. 参考资料
1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. CFS 调度器
2.1 概述
CFS,是 Completely Fair Scheduler 的缩写,翻译过来就是 完全公平调度器,由 Ingo Molnar 实现,在 Linux 2.6.23 中合入的新的 “桌面” 进程调度器。
CFS 调度器 80% 的设计可以用一句话来概括:CFS 基本上是在真实硬件上模拟了一个理想、精确的多任务 虚拟 CPU。我们将这个虚拟 CPU 的运行能力定义为 1,假定当前有 nr_running 个任务在虚拟 CPU上运行,则每个任务精准的占用虚拟 CPU 1/nr_running 的运行能力(或 运行时间)。例如有 2 个任务在运行,假定将 虚拟 CPU 的运行能力设定为 100%,那么每个任务占用 虚拟 CPU 50% 的运行能力(或 运行时间)。为了描述方便,在这里先将任务占用的 虚拟 CPU 的运行时间,称作 虚拟运行时间(virtual runtime),这和后文的 物理 CPU 的 物理运行时间 相对应。
在 CFS 调度器中,并非真的将 物理 CPU 的物理运行能力(或 物理时间)平均分配给所有可运行任务,CFS 仍然要处理任务优先级:即优先级更高的任务,仍然会分配更多 物理 CPU 的物理运行时间 给它们。这看起来似乎和 CFS 调度器的 完全公平调度 宗旨相矛盾,但事实是,CFS 调度器只是尽量保证每个任务占用的 虚拟运行时间(virtual runtime) 一样,而任务占用的 物理运行时间,仍然由任务优先级来体现。正如世界不可能完全公平一样,在 CFS 调度器中,分配给每个任务的 虚拟运行时间(virtual runtime) ,CFS 也只是尽量保证它们一致,不可能达到理想状态的完全一致。
2.2 一些实现细节
在 CFS 调度器中,虚拟运行时间(virtual runtime) 通过每个任务的 p->se.vruntime(以纳秒单位)来表示和跟踪,这样,就可以准确地标记时间戳并测量任务应该获得的预期 CPU 时间。其中,p 指向一个 struct task_struct 结构体。
/* include/linux/sched.h */struct sched_entity {.../** 进程的虚拟运行时间 = 进程的实际运行时间 / 相对权重** 进程的 实际运行时间 是一段一段的,所以进程的 虚拟运行时间 也是一段一段增长的。** 进程的 虚拟运行时间 还会在 进程入队时 与 运行队列中的最小虚拟时间 相比较,如* 果更小的话会直接进行增加,并不对应 实际的运行时间。为什么要这么做呢?因为有的* 进程可能会因长时间睡眠,导致其 虚拟运行时间 小于运行队列中所有进程中的 最小虚* 拟运行时间,这样的进程一旦运行起来,会因为其 虚拟运行时间 小,占据 CPU 的时间* 就会长,对其它进程就不公平了。*/u64 vruntime;...
};struct task_struct {...const struct sched_class *sched_class; /* 如果任务使用 CFS 调度,则为 &fair_sched_class */struct sched_entity se; /* CFS 类进程调度参数 */...
};
在理想的 虚拟 CPU 上,在任何时刻,所有任务 虚拟运行时间值 p->se.vruntime 都保持相同的值。
CFS 调度器,其任务选择逻辑基于 p->se.vruntime 值:CFS 始终尝试运行具有最小 p->se.vruntime 值的任务(即到目前为止虚拟执行时间(virtual runtime)最小的任务)。CFS 始终尝试在可运行任务之间平均分配 虚拟 CPU时间 ,尽可能接近理想的多任务 虚拟 CPU。
CFS 设计的其余部分大部分都脱离了这个非常简单的概念,有一些其它附加修饰,如任务的 nice 值,各种识别睡眠任务的算法等等。
2.3 运行队列:红黑树
CFS 不同于以往的调度器,它不使用运行队列以往的旧数据结构,而是使用按时间排序的 红黑树(rbtree) 来构建未来任务执行的时间线,而它之前 O(1) 调度器使用位图进行任务调度管理。
CFS 还维护 rq->cfs.min_vruntime 值,该值是一个单调递增值,用于跟踪运行队列中所有任务中的最小 vruntime。该值用于尽可能将新激活的调度实体(struct sched_entity,即任务)放置在红黑树的左侧。由于该值一直使用 min_vruntime 单调递增累加,所以也可用来跟踪系统完成的工作总量。
/* kernel/sched/sched.h *//* CFS-related fields in a runqueue */
struct cfs_rq {...u64 min_vruntime; /* CFS 调度算法 运行队列中 进程 的 最小 虚拟运行时间 */...
};/** This is the main, per-CPU runqueue data structure.** Locking rule: those places that want to lock multiple runqueues* (such as the load balancing or the thread migration code), lock* acquire operations must be ordered by ascending &runqueue.*/
struct rq {...struct cfs_rq cfs;...
};DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); /* 每 CPU 的运行队列 */
运行队列的权重通过 rq->cfs.load 值进行统计,该值是运行队列上排队的任务权重的总和:
/* kernel/sched/sched.h *//* CFS-related fields in a runqueue */
struct cfs_rq {/** 运行队列的权重, 等于其上所有进程的权重之和。* 进程在入队出队时,也会相应地从运行队列中加上减去其自身的权重。*/struct load_weight load;...
};
CFS 维护一个按时间排序的 红黑树(rbtree),即所有可运行的任务都按 p->se.vruntime 键排序,然后CFS 从这棵树中挑选最左边(即 p->se.vruntime 最小)的任务执行。随着时间往后推移,执行的任务越来越多地被放入树中,执行时间更少的任务逐渐往红黑树左边移动,执行时间更多的任务往红黑树右边移动,如此循环往复。
2.4 一些特征
CFS 使用纳秒级精度,对任务的虚拟运行时间的统计,它不依赖于 jiffies 或 HZ 值。因此,CFS 调度器没有像以前的调度器那样的时间片概念,也没有任何启发式方法。不使用启发式方法这一点,这使得 CFS 不容易受到针对启发式调度的攻击。
CFS 对任务 nice 值 和 SCHED_BATCH 策略任务 的处理比以往的调度器更优。
CFS 对 SMP 架构下的负载均衡代码进行了清理,使得负载均衡逻辑更加简单。
2.5 调度策略
CFS 实现了 3 种调度策略:
SCHED_NORMAL,以往也叫SCHED_OTHER:用于常规任务。SCHED_BATCH:适用于没有用户交互行为的后台进程,用户对该类进程的响应时间要求不高,但对吞吐量要求较高,因此调度器会在完成所有SCHED_NORMAL的任务之后让该类任务不受打扰地跑上一段时间,这样能够最大限度地利用缓存。SCHED_IDLE:这类调度策略被用于系统中优先级最低的任务,只有在没有任何其他任务可运行时,调度器才会将运行该类任务。
2.6 调度器类别
Linux 同时支持多种类型调度器类别,CFS 调度只是其中的一种,实现在文件 sched/fair.c 中。而像其它的调度类别如实现 SCHED_FIFO 和 SCHED_RR 调度策略的实时调度器,实现在文件 sched/rt.c 中。
调度类是通过 struct sched_class 结构体实现的,该结构体包含一些列回调,在发生特定事件时被调用。struct sched_class 结构体内容如下:
/* kernel/sched/sched.h */struct sched_class {const struct sched_class *next;/** 将进程 @p 放入运行队列 @rq 。* 在任务进入可运行状态时调用。* 它将调度实体(任务)放入红黑树中,并递增 nr_running 变量。*/void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);/** 将进程 @p 移出运行队列 @rq 。* 当任务不再可运行时,将调用此函数以将相应的调度实体移出红黑树,并递减 * nr_running 变量。*/void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);/** 当前进程主动让出 CPU , 即移出运行队列,但 其状态依然是 runnable ,* 然后将另一进程加入运行队列。* 可通过系统调用 sys_sched_yield() 触发。*/void (*yield_task) (struct rq *rq);/* 当前进程主动让出 cpu 给进程组内进程 @p */bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);/** 被唤醒进程的抢占逻辑:检查 @p 是否会抢占 @rq 中当前正在运行的进程. * 通常情况下是在 @p 进入 runnable 态时,检查 @p 是否会抢占当前正在运* 行的进程。*/void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);/** It is the responsibility of the pick_next_task() method that will* return the next task to call put_prev_task() on the @prev task or* something equivalent.** May return RETRY_TASK when it finds a higher prio class has runnable* tasks.*//* * 挑选下一可执行进程, 且以 @prev 为参数, 调用 put_prev_task() . ** 通常返回挑选的下一可执行进程, 但当发现更高优先级调度类别有可运行进程时, * 返回 RETRY_TASK .*/ struct task_struct * (*pick_next_task) (struct rq *rq,struct task_struct *prev,struct rq_flags *rf);void (*put_prev_task) (struct rq *rq, struct task_struct *p);#ifdef CONFIG_SMP/** 为进程 @p 选择运行队列。* 当系统调用 fork() + exec() 创建一个新的进程时,在 SMP 系统中* 选择一个合理的 runqueue 来将该进程入队。Scheduler 此时需要考* 虑 负载均衡 问题。*/int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);void (*migrate_task_rq)(struct task_struct *p);void (*task_woken) (struct rq *this_rq, struct task_struct *task);/* 设置进程的 cpu affinity */void (*set_cpus_allowed)(struct task_struct *p, const struct cpumask *newmask);void (*rq_online)(struct rq *rq); /* cpu online */void (*rq_offline)(struct rq *rq); /* cpu offline */
#endifvoid (*set_curr_task) (struct rq *rq);void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);void (*task_fork) (struct task_struct *p);void (*task_dead) (struct task_struct *p);/** The switched_from() call is allowed to drop rq->lock, therefore we* cannot assume the switched_from/switched_to pair is serliazed by* rq->lock. They are however serialized by p->pi_lock.*/void (*switched_from) (struct rq *this_rq, struct task_struct *task); /* @task 从 当前调度类别 切换到 其他调度类别 */void (*switched_to) (struct rq *this_rq, struct task_struct *task); /* @task 从 其他调度类别 切换到 当前调度类别 */void (*prio_changed) (struct rq *this_rq, struct task_struct *task, /* 优先级变更时的抢占逻辑 */int oldprio);/* 获取分配给进程 @task 的时间片 (sys_sched_rr_get_interval()) */unsigned int (*get_rr_interval) (struct rq *rq, struct task_struct *task);/* 更新当前进程运行时间统计信息 */void (*update_curr) (struct rq *rq);#define TASK_SET_GROUP 0
#define TASK_MOVE_GROUP 1#ifdef CONFIG_FAIR_GROUP_SCHEDvoid (*task_change_group) (struct task_struct *p, int type);
#endif
};
CFS 调度器类别定义如下:
/** All the scheduling class methods:*/
const struct sched_class fair_sched_class = {.next = &idle_sched_class,.enqueue_task = enqueue_task_fair,.dequeue_task = dequeue_task_fair,.yield_task = yield_task_fair,.yield_to_task = yield_to_task_fair,.check_preempt_curr = check_preempt_wakeup,.pick_next_task = pick_next_task_fair,.put_prev_task = put_prev_task_fair,#ifdef CONFIG_SMP.select_task_rq = select_task_rq_fair,.migrate_task_rq = migrate_task_rq_fair,.rq_online = rq_online_fair,.rq_offline = rq_offline_fair,.task_dead = task_dead_fair,.set_cpus_allowed = set_cpus_allowed_common,
#endif.set_curr_task = set_curr_task_fair,.task_tick = task_tick_fair, /* cfs 类定时器周期调度接口: scheduler_tick() -> task_tick_fair() */.task_fork = task_fork_fair, /* 子进程创建时, 更新其虚拟时间 */.prio_changed = prio_changed_fair,.switched_from = switched_from_fair,.switched_to = switched_to_fair,.get_rr_interval = get_rr_interval_fair,.update_curr = update_curr_fair,#ifdef CONFIG_FAIR_GROUP_SCHED.task_change_group = task_change_group_fair,
#endif
};
2.7 扩展:组调度
通常,CFS 调度器对单个任务进行操作,并努力为每个任务提供公平的 CPU 时间。有时,可能需要对任务进行分组,并为每个此类任务组提供公平的 CPU 时间。例如,可能需要首先为系统上的每个用户提供公平的 CPU 时间,然后再为属于用户的每个任务提供公平的 CPU 时间。
CONFIG_CGROUP_SCHED 配置涵盖的功能,试图实现这一目标:它允许对任务进行分组,并在这些组之间公平地分配 CPU 时间。
CONFIG_RT_GROUP_SCHED 允许对实时任务(即使用 SCHED_FIFO 和 SCHED_RR 调度策略的任务)进行分组。
CONFIG_FAIR_GROUP_SCHED 允许对 CFS 任务(即使用 SCHED_NORMAL 和SCHED_BATCH 调度策略的任务)进行分组。
开启了 CONFIG_FAIR_GROUP_SCHED 后,将为使用 cgroups 伪文件系统创建的每个组创建一个 cpu.shares 文件。请参阅以下示例步骤,以创建任务组并使用 cgroups 伪文件系统 修改 CPU 份额:
# mount -t tmpfs cgroup_root /sys/fs/cgroup
# mkdir /sys/fs/cgroup/cpu
# mount -t cgroup -ocpu none /sys/fs/cgroup/cpu
# cd /sys/fs/cgroup/cpu# mkdir multimedia # create "multimedia" group of tasks
# mkdir browser # create "browser" group of tasks# #Configure the multimedia group to receive twice the CPU bandwidth
# #that of browser group# echo 2048 > multimedia/cpu.shares
# echo 1024 > browser/cpu.shares# firefox & # Launch firefox and move it to "browser" group
# echo <firefox_pid> > browser/tasks# #Launch gmplayer (or your favourite movie player)
# echo <movie_player_pid> > multimedia/tasks
以上这一系列操作,分别为 多媒体程序 和 浏览器程序 创建了两个任务分组,并指定了它们各自的 CPU 配额。
注意,以上这些配置项都依赖于 CONFIG_CGROUPS,并允许管理员使用 cgroup 伪文件系统创建任务组。更多 cgroups 功能,读者可查阅相关资料。
3. 参考资料
[1] CFS Scheduler
[2] Completely Fair Scheduler
[3] 2.2.3 核心概念 - 调度策略
相关文章:
Linux CFS 调度器 (1):概述
文章目录 1. 前言2. CFS 调度器2.1 概述2.2 一些实现细节2.3 运行队列:红黑树2.4 一些特征2.5 调度策略2.6 调度器类别2.7 扩展:组调度 3. 参考资料 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失ÿ…...
HBase中Master初始化错误~
ERROR:org.apache.hadoop.hbase.PleaseHoldException:Master is initializing 1、停止HBase运行 2、启动zookeeper中的zkCli.sh服务 ./zookeeper/bin/zkCli.sh 3、执行完毕显示以下结果,删除habse文件夹 4、重新启动HBase即可。...
Hive on Spark版本兼容性
Hive on Spark仅在特定版本的Spark上进行测试,因此给定版本的Hive只能保证与特定版本的Spark一起工作。其他版本的Spark可能与给定版本的Hive一起工作,但不能保证。以下是Hive版本及其对应的Spark版本列表: 详情参考官方文档:http…...
grep命令知多少
引言 1. grep命令的重要性 在Linux系统中,grep是一个不可或缺的文本处理工具,它允许用户快速搜索文件中的文本模式。这个命令的名称来源于Global Regular Expression Print,即全局正则表达式打印,它源自UNIX早期的ed文本编辑器。…...
[java]windows和linux下jdk1.8安装包所有版本系列下载地址汇总
【windows jdk1.9系列下载地址】 序号java版本下载地址1java-jdk9-jdk-9.0.1-windows-x64-bin.zip点我下载 【windows jdk1.8系列下载地址】 序号java版本下载地址1java-jdk1.8-jdk-8u202-windows-x64.zip点我下载2java-jdk1.8-jdk-8u201-windows-x64.zip点我下载3java-jdk1…...
Electron+Vue开源软件:洛雪音乐助手V2.8畅享海量免费歌曲
洛雪音乐助手是一款功能全面且完全免费的开源音乐软件,支持在Windows、Android和iOS平台上使用。 平台支持: 桌面版:采用Electron Vue技术栈开发,支持Windows 7及以上版本、Mac OS和Linux,具有广泛的用户群体覆盖。 …...
CAPL通过addTimeToMeasurementStartTime或者getLocalTime获取本地时间
文章目录 getLocalTimeaddTimeToMeasurementStartTimegetLocalTime long tm[9]; getLocalTime(tm); // now tm contains the following entries: // tm[0] = 3; (seconds) // tm[1] = 51; (minutes) // tm[2] = 16; (hours)...
谷歌上架,APP被移除了,没封号,换个包名还能重新提审上架?
对于在Google Play上架应用的开发者来说,尤其是那些矩阵式上架马甲包的开发者,可能已经遭遇过无数次应用被暂停或移除的情况了。通常这种情况下,账号也随之会被封,且大多数开发者认为,没有立马收到封号邮件的话&#x…...
Docker部署MaxKB 知识库(提高问答命中率)
前言 上一篇文章简单的介绍了下MaxKB,这一篇文章就讲如何部署MaxKB。 MaxKB实现逻辑也比较简单,如下图。 安装 修改Docker镜像源 由于不可抗力,部分源已经无法使用,需要修改以下的源地址来拉取镜像。如果是linux,…...
LeetCode739每日温度
题目描述 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 解析 每次往栈中…...
【Qt】Qt中的几种Timer
1. QObject::startTimer int QObject::startTimer(int interval, Qt::TimerType timerType Qt::CoarseTimer) int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType Qt::CoarseTimer)每次时间到了会调用虚函数timerEvent() 2. QTimer 3. QBa…...
Excel 多列组合内容循环展开
某表格 A 列是编号,其他列是用逗号分隔的意义不同的分类列 ABCDEFG1Assembly#ProductTypeUnit ConfigNominal CapacitySupply VoltageGenerationCase Construction23H1012290001CMD,P24,36FAA,B33H1012290002CMD,P48,60FA,BA,B43H1012290003CMD,P24,36B,C,D,EAA,B …...
Vue2+Element-ui实现el-table表格自适应高度
效果图 新建指令 Vue.directive(height, {inserted(el, _binding, vnode) {const paginationRef vnode.context.$refs.paginationRefconst calculateHeight () > {const windowHeight window.innerHeightconst topOffset el.getBoundingClientRect().topconst otherEle…...
【人工智能】开发AI可能获刑?加州1047草案详解
引言 随着人工智能(AI)技术的飞速发展,其应用领域不断扩展,但同时也引发了诸多争议和监管问题。近期,加州参议院以32比1的压倒性投票通过了1047号草案,又称《前沿人工智能模型安全可靠创新法案》。这一草案…...
机器学习二分类数据集预处理全流程实战讲解
本文概述 本文对weatherAUS数据集进行缺失值分析并剔除高缺失特征,合理填补剩余缺失值,利用相关性筛选关键特征,采用多种机器学习模型(如逻辑回归、随机森林等)在80%训练集上训练,并在20%测试集上预测明日降…...
大模型应用:LangChain-Golang核心模块使用
1.简介 LangChain是一个开源的框架,它提供了构建基于大模型的AI应用所需的模块和工具。它可以帮助开发者轻松地与大型语言模型(LLM)集成,实现文本生成、问答、翻译、对话等任务。LangChain的出现大大降低了AI应用开发的门槛,使得任何人都可以…...
【Tkinter界面】Canvas 图形绘制(03/5)
文章目录 一、说明二、画布和画布对象2.1 画布坐标系2.2 鼠标点中画布位置2.3 画布对象显示的顺序2.4 指定画布对象 三、你应该知道的画布对象操作3.1 什么是Tag3.2 操作Tag的函数 https://www.cnblogs.com/rainbow-tan/p/14852553.html 一、说明 Canvas(画布&…...
【CS.PL】Lua 编程之道: 基础语法和数据类型 - 进度16%
2 初级阶段 —— 基础语法和数据类型 文章目录 2 初级阶段 —— 基础语法和数据类型2.0 关键字(keywords) 🔥2.1 注释与标识符2.1.1 注释2.1.2 标识符 2.2 变量与赋值2.2.1 所有变量默认是全局变量 ≠ local, 有一个例外2.2.2 local变量是局部变量, 以end作为边界2.…...
centos7 xtrabackup mysql 基本测试(3)---虚拟机环境 安装mysql
centos7 xtrabackup mysql 基本测试(3)—虚拟机环境 安装mysql centos7 安装 mysql5.7 可以在运行安装程序之前导入密钥: sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022第一步、下载MySQL 安装包: sudo w…...
Java Native Interface 使用指南
我们知道Java本身的实现,很大一部分是用C写的。实际上,Java也允许我们和原生平台的代码进行交互。 Java定义了一个接口规范,就叫做Java Native Interface,通过这个接口规范,我们就可以让Java代码运行原生平台的代码。…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...
