Linux CFS调度器简介

文章目录

  • 前言
  • 一、概要
  • 二、实现
    • 2.1 简介
    • 2.2 算法实现
    • 2.3 内核源码
  • 三、特点
  • 四、调度策略
  • 五、调度类
  • 参考资料

前言

早期的Linux调度器采用了简化的设计,显然并不针对具有许多处理器甚至超线程的大规模架构。Linux 1.2调度器使用循环队列对可运行任务进行管理,并采用循环调度策略。这个调度器对于添加和删除进程非常高效(使用锁来保护结构)。简而言之,这个调度器并不复杂,但简单且快速。

Linux 2.2版本引入了调度类的概念,允许为实时任务、非可抢占任务和非实时任务设置调度策略。2.2调度器还包括对对称多处理(SMP)的支持。

2.4内核包含了一个相对简单的调度器,它在O(N)时间内运行(因为它在每个调度事件中迭代所有任务)。2.4调度器将时间划分为时期,在每个时期内,每个任务都可以执行其时间片的时间。如果一个任务没有使用完其时间片,那么剩余时间片的一半将被添加到新的时间片中,以使其在下一个时期中执行时间更长。调度器只需要迭代任务,应用一个好度函数(度量)来确定下一个要执行的任务。尽管这种方法相对简单,但它相对低效,缺乏可扩展性,并且对于实时系统来说并不强大。它也缺乏利用新的硬件架构(如多核处理器)的功能。

早期的2.6调度器被称为O(1)调度器,旨在解决2.4调度器的许多问题。即调度器不需要迭代整个任务列表来确定下一个要调度的任务(因此得名O(1),表示它更高效且可扩展性更好)。O(1)调度器通过在一个运行队列中跟踪可运行任务(实际上,对于每个优先级级别,有两个运行队列,一个用于活动任务,一个用于过期任务),这意味着为了确定下一个要执行的任务,调度器只需从特定的活动优先级运行队列中出队即可。O(1)调度器具有更好的可扩展性,并结合了交互性指标和许多启发式方法,以确定任务是I/O绑定还是处理器绑定。但是O(1)调度器在内核中变得臃肿。用于计算启发式方法的大量代码基本上难以管理,并且对于纯粹主义者来说,缺乏算法实质。

面对O(1)调度器及其他外部压力,需要进行一些改变。这种改变来自于Con Kolivas的内核补丁,其中包括他之前在阶梯调度器上的工作,引入了他的Rotating Staircase Deadline Scheduler (RSDL)。这项工作的结果是一个简单设计的调度器,将公平性与有界延迟相结合。Kolivas的调度器给很多人留下了深刻印象(有人呼吁将其纳入当前的2.6.21主线内核),因此可以明显看到调度器的改变正在途中。接着,O(1)调度器的创建者Ingo Molnar基于Kolivas的工作思想开发了CFS。

CFS(Completely Fair Scheduler)是Linux操作系统中的一种新的进程调度器,与其竞争对手RSDL相比,CFS的选择在某些圈子中引起了很大争议。为了澄清发生了什么以及CFS相对于旧调度器的作用,需要一些历史背景。

在Linux 2.5的开发过程中,来自Ingo Molnar的’O(1)'进程调度器(PS)被合并以取代从2.4继承的调度器。O(1) PS的设计旨在解决2.4调度器存在的可扩展性问题 - 性能改进非常显著,以至于O(1) PS成为商业Linux发行版中最常被反向移植到2.4的特性之一。然而,负责调度进程的算法并没有发生太大改变,因为它们被认为是“足够好”,或者至少没有被视为关键问题。但是,这些算法在用户所感知的“交互性”方面可能会产生巨大影响。例如,如果一个或多个进程开始执行无限循环,并且由于这些占用CPU的循环进程,调度器没有为已经存在的负责实现用户界面(如X.org、kicker、firefox、openoffice.org等)的非循环进程分配足够的CPU时间,用户会感觉这些程序对用户的操作反应不够流畅。更糟糕的是,在音乐播放器的情况下,你的音乐可能会出现跳跃。

O(1)进程调度器PS和之前的调度器一样,试图改善这些情况,并且大多数时候表现良好。然而,许多用户报告了一些特殊情况和非特殊情况,新的调度器并没有按预期工作。其中一个用户是Con Kolivas,尽管他在内核编程领域没有经验,但他试图微调调度算法,而不是替换它们。他的工作取得了成功,他的补丁被纳入了主内核,其他人(Mike Galbraith、Davide Libenzi、Nick Piggin)也帮助调整了调度器。但并非所有特殊情况都消失了,当尝试修复其中一个问题时,可能会出现新问题。Con发现,“交互性估计器”——PS用来尝试判断哪些进程更具“交互性”,因此需要更多关注,以便用户感知其桌面更具“交互性”的一段代码,引发了比解决问题更多的问题。与其原始目的相反,交互性估计器无法解决PS中存在的所有“交互性”问题,而且尝试修复一个问题可能会导致另一个问题的出现。这是一个典型的算法使用统计数据和启发式方法来预测未来并在其上失败的案例。Con设计了一个名为RSDL的新的调度器,它取消了交互性估计代码。相反,他的调度器基于“公平性”的概念:进程被平等对待,并被分配相同的时间片(有关此调度器的更多细节,请参阅LWN文章:https://lwn.net/Articles/224865/)。这个调度器在这些特殊情况下改善了用户所感知的“交互性”。

这个PS原本打算合并,但Ingo Molnar(O(1)的创建者)创建了另一个名为CFS(完全公平调度器)的新的PS,其中一个基本设计元素是Con的PS证明了“公平调度”的优越性。CFS得到了一些黑客的好评,这帮助Ingo使CFS成为主线内核的一个很好的进程调度器替代方案。'公平性’是RSDL和CFS之间唯一共享的概念,这也是它们的相似之处终止的地方,甚至’公平性’的定义也非常不同:RSDL使用了’严格’的公平性定义。但是CFS将任务的睡眠时间包括在公平性指标中:这意味着在CFS中,睡眠任务(通常运行用户感觉为’交互式’的代码,如X.org、mp3播放器等)获得比运行任务更多的CPU时间(与RSDL的’严格公平性’不同,RSDL对它们采用严格的公平性处理),但这一切都受到公平性引擎的控制。这种设计兼顾了公平性和交互性,但没有使用交互性估计器。

CFS相对于旧的主线调度器和RSDL还有其他一些不同之处:它使用一个按时间顺序排列的红黑树(time-ordered rbtree)来构建未来任务执行的’时间轴’,以尝试避免常规调度器和RSDL调度器可能出现的’数组切换’问题。CFS还使用纳秒级粒度的计时,并且不依赖于任何滴答数或其他HZ细节;实际上,它没有传统的’timeslices’概念:切片决策是动态的,而不是静态的,并且切片没有持久性(即切片不是以传统意义上的方式’给予’任务并被任务’消耗’),因为CFS能够通过纳秒级计时准确追踪任务的完整执行历史。

最终,CFS被选择作为当前’O(1)'进程调度器的替代品,而不是RSDL。必须指出的是,无论是RSDL还是CFS,它们都是比主线内核中的调度器更好的调度器,而正是Con首创了使用’公平性’的概念而不是’交互性估计’的想法,但这并不意味着CFS不应该作为主线内核进程调度器的最终替代品被合并;这也不意味着RSDL不是一个很好的替代品。

可以看到CFS调度器是用来解决交互性进程响应快慢的问题,更适用于桌面操作系统;对于服务器来说,更注重吞吐性,CFS调度器和O1调度器没啥差别。

在一个混杂着大量计算型进程和IO交互进程的系统中,CFS调度器对待IO交互进程要比O(1)调度器更加友善和公平。

O(1)调度器直接将优先级线性映射到了时间片(进程的优先级和进程可运行的时间片进行了强映射),以表示差异化。
CFS调度器则直接将进程优先级映射到了CPU时间份额,以表示差异化。

优先级和时间片本来就是两个概念,二者中间还得有个变量沟通才可以。优先级高只是说明该进程能运行的久一些,但是到底久多少,并不是仅仅优先级就能决定的,还要综合考虑,换句话距离来说,如果只有一个进程,那么即便它优先级再低,它也可以永久运行,如果系统中有很多的进程,即便再高优先级的进程也要让出一些时间给其它进程。

CFS考虑到系统中总体的进程情况,将优先级转换为权重,将时间片转换为份额。最终的坐标系应该是 权重占比/时间片 坐标系而不是 权重(或者优先级)/时间片 。

CFS的时间片是动态的,是系统负载均衡以及其优先级的函数,这便可以把进程调度动态适应到系统最佳,以节省切换开销。

一、概要

CFS(Completely Fair Scheduler)是由Ingo Molnar实现并在Linux 2.6.23中合并的新的“桌面”进程调度器。它是对以前的普通调度器(vanilla scheduler)的SCHED_OTHER互动性代码的替代。

CFS的设计中,80%可以用一句话总结:CFS基本上在真实硬件上模拟了一个“理想的、精确的多任务CPU”。

“理想的多任务CPU”是一个(不存在的) CPU,它具有100%的物理能力,并且可以以精确相等的速度并行运行每个任务,每个任务运行在1/nr_running的速度上。例如,如果有2个任务正在运行,那么它会以每个任务50%的物理能力运行,也就是实际上是并行运行。

在真实硬件上,我们一次只能运行一个任务,因此我们必须引入“虚拟运行时间”的概念。任务的虚拟运行时间指定了它在上述理想多任务CPU上下一个时间片开始执行的时间。实际上,任务的虚拟运行时间是其实际运行时间与正在运行的任务总数的归一化结果。

CFS(完全公平调度器)的主要思想是在为任务提供处理器时间时保持平衡(公平性)。这意味着进程应该被给予公平的处理器时间。当任务的时间不平衡(意味着一个或多个任务与其他任务相比没有得到公平的时间)时,那些不平衡的任务应该被给予执行的时间。

为了确定平衡,CFS维护了所谓的虚拟运行时间,即为给定任务提供的时间量。任务的虚拟运行时间越小(意味着任务被允许访问处理器的时间越少),它对处理器的需求就越高。CFS还包括了“睡眠公平性”的概念,以确保当前不可运行的任务(例如,等待I/O的任务)在它们最终需要处理器时能够获得相当的份额。

但与以前的Linux调度器在运行队列中维护任务不同,CFS维护一个按时间排序的红黑树(如下图所示)。红黑树是一种具有一些有趣和有用属性的树。首先,它是自平衡的,这意味着树中的任意路径长度都不会超过其他路径长度的两倍。其次,对树的操作在O(log n)的时间内完成(其中n是树中节点的数量)。这意味着您可以快速高效地插入或删除一个任务。
在这里插入图片描述
在按时间排序的红黑树中存储任务(表示为sched_entity对象),具有最迫切需要处理器的任务(虚拟运行时间最低)存储在树的左侧,而对处理器需求最小的任务(虚拟运行时间最高)存储在树的右侧。为了保持公平性,调度器选择红黑树的最左边的节点作为下一个要调度的任务,以保持公平性。任务通过将其执行时间添加到虚拟运行时间来记录其在CPU上的时间,如果可运行,则重新插入到树中。通过这种方式,树的左侧的任务被给予执行时间,并且树的内容从右侧向左侧迁移,以保持公平性。因此,每个可运行的任务都会追逐其他任务,以在可运行任务集合中保持执行的平衡。

二、实现

2.1 简介

CFS有一些有趣的方面。首先,它完全取消了运行队列数组的使用。相反,CFS使用单个红黑树来跟踪所有处于可运行状态的进程。在树的最左节点出现的进程是在任何给定时间最有资格运行的进程。因此,理解这个调度器的关键是了解它如何计算用于将进程插入树中的键值。

这个计算相当简单。当一个任务进入运行队列时,记录下当前时间。当进程等待CPU时,调度器跟踪它本应获得的处理器时间量;这个权益简单地是等待时间除以运行进程数(根据不同优先级值进行修正)。在实际情况下,键值是进程应获得的CPU时间量,而较高优先级的进程会稍微获得提升。因此,进程的短期优先级将根据它是否获得了公平的处理器份额而变化。

只是略微简化地说,上述讨论涵盖了CFS调度器的全部内容。它没有跟踪睡眠时间,也没有尝试识别交互式进程等等。从某种意义上说,CFS调度器甚至取消了时间片的概念;一切都取决于给定进程是否获得了根据试图运行的进程数而应得的CPU份额。CFS调度器提供了一个可调整的参数:"granularity"值,用于描述调度器为了保持公平性而切换进程的速度。较低的granularity值会导致更频繁的切换;这个设置会降低交互响应的延迟,但可能会稍微降低吞吐量。服务器系统可能会在较高的granularity值下运行得更好。

2.2 算法实现

在CFS中,虚拟运行时间通过每个任务的p->se.vruntime(纳秒单位)值来表示和跟踪。通过这种方式,可以准确地记录和测量任务应该获得的“预期CPU时间”。

一个小细节是,在“理想”的硬件上,任何时候所有任务的p->se.vruntime值都相同,也就是说,任务会同时执行,没有任务会从“理想”的CPU时间份额中“失衡”。

CFS的任务选择逻辑基于p->se.vruntime值,因此非常简单:它总是尝试运行具有最小p->se.vruntime值的任务(即到目前为止执行最少的任务)。CFS始终尽可能地将CPU时间在可运行的任务之间分配得接近“理想的多任务硬件”。

CFS的大部分设计都是基于这个非常简单的概念。

CFS的设计非常激进:它不使用旧的运行队列数据结构,而是使用一个按时间排序的红黑树来构建未来任务执行的“时间线”,因此没有“数组切换”现象(这会影响到以前的普通调度器和RSDL/SD)。

CFS还维护了rq->cfs.min_vruntime值,它是一个单调递增的值,跟踪运行队列中所有任务中最小的vruntime。系统完成的总工作量通过min_vruntime来跟踪;该值被用于尽可能将新激活的实体放在树的左侧。

运行队列中正在运行的任务总数通过rq->cfs.load值来统计,该值是排队在运行队列上的任务权重的总和。

CFS维护了一个按时间排序的红黑树,其中所有可运行的任务按照p->se.vruntime键进行排序。CFS从这棵树中选择“最左边”的任务并坚持执行。随着系统的前进,执行的任务被逐渐放置到树的右侧,以便给每个任务一个机会成为“最左边的任务”,从而在确定的时间内获得CPU时间。

总结起来,CFS的工作方式如下:它运行一个任务一小段时间,当任务调度(或发生调度器时钟中断)时,任务的CPU使用情况被“记账”:刚刚使用物理CPU的时间被添加到p->se.vruntime中。一旦p->se.vruntime变得足够高,以至于另一个任务成为它维护的按时间排序的红黑树的“最左边的任务”(加上一小段与最左边任务的“粒度”距离,以避免过度调度任务和缓存垃圾),则选择新的最左边任务并抢占当前任务。

2.3 内核源码

在Linux中,所有任务都由一个名为task_struct的任务结构表示。该结构(以及与之相关的其他结构)完整描述了任务,包括任务的当前状态、堆栈、进程标志、优先级(静态和动态)等等。但是,由于并非所有任务都是可运行的,因此在task_struct中找不到与CFS相关的字段。相反,创建了一个名为sched_entity的新结构来跟踪调度信息。

// linux-4.10.1/include/linux/sched.hstruct sched_entity {struct load_weight	load;		/* for load-balancing */struct rb_node		run_node;struct list_head	group_node;unsigned int		on_rq;......u64			vruntime;	
}struct task_struct {......struct sched_entity se;	......
}

sched_entity结构用于存储任务的调度信息,包括任务的虚拟运行时间、调度实体的优先级以及其他与CFS调度器相关的字段。通过sched_entity结构,CFS可以跟踪每个任务的运行时间和调度状态,并根据任务的需求进行公平调度。
在这里插入图片描述
各种结构之间的关系如上图所示。树的根节点通过cfs_rq结构中的rb_root元素进行引用。红黑树中的叶子节点不包含任何信息,但内部节点表示一个或多个可运行的任务。红黑树中的每个节点都由一个rb_node表示,其中只包含子节点的引用和父节点的颜色信息。rb_node包含在sched_entity结构中,该结构包括rb_node引用、负载权重和各种统计数据。最重要的是,sched_entity包含一个64位的vruntime字段,用于表示任务运行的时间量,并作为红黑树的索引。最后,task_struct位于顶部,完整描述了任务,并包含sched_entity结构。

三、特点

CFS的设计非常激进:它不使用运行队列,而是使用一个按时间排序的rbtree来构建未来任务执行的“时间轴”,因此没有“数组切换”现象(这是原始调度器和RSDL/SD所受影响的)。

CFS使用纳秒级的精确度进行计算,不依赖于任何jiffies或其他HZ细节。因此,CFS调度器没有像以前的调度器那样关于“时间片”的概念,并且没有任何启发式规则。中心可调参数为"/proc/sys/kernel/sched_granularity_ns",可以用来根据不同的工作负载从"桌面"(低延迟)到"服务器"(良好批处理)进行调整。默认设置适用于桌面工作负载,并且还处理SCHED_BATCH工作负载。

CFS保证的是每时每刻的公平,cfs依据的是进程的执行时间,利用的是补偿原理,cfs让进程先超前运 行,然后补偿别的进程,这样很合理。另外cfs不用任何启发算法,只是一个虚拟时钟就够了,因为当进程睡眠的时候,其虚拟时钟就不走了,这样当然落后于别 的进程的虚拟时钟,理应得到补偿。

可以用来调整调度器以适应“桌面”(即低延迟)到“服务器”(即良好批处理)负载。它的默认设置适用于桌面工作负载。CFS调度器模块也处理SCHED_BATCH。

CFS调度器对于nice级别和SCHED_BATCH的处理比以前的普通调度器更强大:这两种类型的工作负载被更积极地隔离。

负载平衡代码在对称多处理(SMP)系统中进行了重新设计和清理。代码不再依赖于运行队列遍历的假设,而是使用来自调度模块的迭代器。这个改变简化了负载平衡代码。

引入了调度类(Scheduling Classes):这是一个可扩展的调度程序模块层次结构。这些模块封装了调度策略的细节,并由调度器核心处理,而核心代码对它们的假设不过多。

该模块以比原始调度器更简单的方式实现了SCHED_FIFO和SCHED_RR的语义。它使用100个运行队列来处理所有100个实时(RT)优先级级别,而不是原始调度器的140个运行队列。它也不需要一个过期数组。

四、调度策略

CFS(完全公平调度器)实现了三种调度策略:
(1)SCHED_NORMAL(传统上称为SCHED_OTHER):这是用于常规任务的调度策略。它用于普通任务的默认调度策略。

(2)SCHED_BATCH:相比于常规任务,该策略不会频繁地进行抢占,从而允许任务运行更长时间并更好地利用缓存,但代价是降低了交互性。这非常适合批处理作业。

(3)SCHED_IDLE:该策略比nice 19的任务优先级还要低,但它不是一个真正的空闲定时器调度器,以避免陷入优先级反转问题,这可能导致系统死锁。

五、调度类

CFS发布还带来了一个意外的特性,几乎让所有关注内核开发领域的人感到惊讶:一个模块化调度器框架。Ingo将其描述为"一个可扩展的调度器模块层次结构",但是,如果是这样的话,它是一个没有分支的层次结构。它是一个按优先级顺序排列的模块简单链表;第一个能够提供可运行任务的调度器模块将决定下一个运行的进程。

新的CFS调度器的设计引入了“调度类(Scheduling Classes)”,这是一种可扩展的调度器模块层次结构。这些模块封装了调度策略的细节,并由调度器核心处理,核心代码不会对它们做过多的假设。

调度类通过sched_class结构来实现,该结构包含了在发生事件时必须调用的函数钩子。

// kernel/sched/sched.hstruct sched_class {const struct sched_class *next;void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);void (*yield_task) (struct rq *rq);bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);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.*/struct task_struct * (*pick_next_task) (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie);void (*put_prev_task) (struct rq *rq, struct task_struct *p);......
}

在这里插入图片描述

● Stop○ No policy
● Deadline○ SCHED_DEADLINE
● Real Time○ SCHED_FIFO○ SCHED_RR
● Fair○ SCHED_NORMAL○ SCHED_BATCH○ SCHED_IDLE
● Idle○ No policy

以下是这些函数钩子的(部分)列表:

enqueue_task(…)

当任务进入可运行状态时调用。它将调度实体(任务)放入红黑树中,并增加nr_running变量。

dequeue_task(…)

当任务不再可运行时,调用此函数将相应的调度实体从红黑树中移除。它减少nr_running变量。

yield_task(…)

除非启用了compat_yield sysctl,否则此函数基本上只是一个dequeue,然后是一个enqueue操作;在这种情况下,它将调度实体放置在红黑树的最右端。

wakeup_preempt(…)

此函数检查进入可运行状态的任务是否应该抢占当前正在运行的任务。

pick_next_task(…)

此函数选择下一个合适的可运行任务。

set_next_task(…)

当任务更改其调度类、更改其任务组或被调度时,调用此函数。

task_tick(…)

此函数主要从时间滴答函数中调用;它可能导致进程切换。它驱动运行抢占。

参考资料

Linux 4.10.0
https://www.kernel.org/doc/html/latest/scheduler/sched-design-CFS.html
https://kernelnewbies.org/Linux_2_6_23#The_CFS_process_scheduler
https://lwn.net/Articles/230574/
https://developer.ibm.com/tutorials/l-completely-fair-scheduler/

https://blog.csdn.net/dog250/article/details/95729830
https://blog.csdn.net/dog250/article/details/96500186
https://zhuanlan.zhihu.com/p/659215677

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

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

相关文章

昆仑万维官宣开源2000亿稀疏大模型Skywork-MoE

6月3日,昆仑万维宣布开源2千亿稀疏大模型Skywork-MoE,性能强劲,同时推理成本更低。 据「TMT星球」了解,Skywork-MoE基于之前昆仑万维开源的Skywork-13B模型中间checkpoint扩展而来,是首个完整将MoE Upcycling技术应用…

北京Profinet转Modbus网关配置调试详解

一、背景:在工业自动化系统中,PLC(可编程逻辑控制器)与流量计之间的通信是非常重要的,以确保数据准确传输并实现控制功能。然而,由于PLC和流量计可能采用不同的通信协议(如Profinet和Modbus&…

探索Java的DNA-JVM字节码深度解析

引言 在Java的世界里,JVM(Java虚拟机)是我们程序运行的心脏。而字节码,作为JVM的血液,携带着程序的执行指令。今天,我们将深入探索Java字节码的奥秘,一窥JVM如何将人类可读的代码转化为机器可执…

【小白向】微信小程序解密反编译教程

# 前言 最近笔者有做到微信小程序的渗透测试,其中有一个环节就是对微信小程序的反编译进行源码分析,所谓微信小程序反编译,就是将访问的小程序进行反向编译拿到部分源码,然后对源码进行安全审计,分析出其中可能存在的…

图形学初识--颜色混合

文章目录 前言正文为什么要有颜色混合?颜色混合常见实现方式?上述颜色混合注意点 结尾:喜欢的小伙伴点点关注赞哦! 前言 本章节补充一下颜色混合的内容,主要包含:为什么要有颜色混合?颜色混合常实现方式&a…

Centos 7 安装刻录至硬件服务器

前言 在日常测试中,会遇到很多安装的场景,今天给大家讲一下centos 7 的安装,希望对大家有所帮助。 一.下载镜像 地址如下: centos官方镜像下载地址https://www.centos.org/download/ 按照需求依次点击下载 二.镜像刻录 镜像刻…

idea springboot woff/woff2/eot/ttf/svg等小图标不显示的问题 - 第515篇

历史文章(文章累计500) 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 《…

Shopify 独立站监控观测最佳实践

Shopify 简介 Shopify 是一个全球领先的电子商务平台,它为商家提供了一整套在线商店解决方案。自 2006 年成立以来,Shopify 已经帮助数百万商家在全球范围内建立和发展他们的在线业务。 监控观测 Shopify 站点对于确保业务连续性、优化用户体验和提高运…

Linux shell编程学习笔记56:date命令——显示或设置系统时间与日期

0 前言 2024年的网络安全检查又开始了,对于使用基于Linux的国产电脑,我们可以编写一个脚本来收集系统的有关信息。在收集的信息中,应该有一条是搜索信息的时间。 1. date命令 的功能、格式和选项说明 我们可以使用命令 date --help 来查看 d…

Kafka之Broker原理

1. 日志数据的存储 1.1 Partition 1. 为了实现横向扩展,把不同的数据存放在不同的 Broker 上,同时降低单台服务器的访问压力,我们把一个Topic 中的数据分隔成多个 Partition 2. 每个 Partition 中的消息是有序的,顺序写入&#x…

LeetCode刷题:反转链表

leetCode真题 206. 反转链表 属于基础简单题目 常见的做法有递归和while循环 递归 // 1. 递归参数和返回值public static ListNode reverseList(ListNode head) {// 1. 递归终止条件if (head null || head.next null) {return head;}// 递归逻辑ListNode last reverseL…

达梦数据库相关SQL及适配Mysql配置总结

🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢…

Windows 系统安装 VisualSVN Server

一.下载 VisualSVN Server VisualSVN-Server 是 SVN 版本控制中服务器端要使用的软件,就是我们提交代码存在安装这个软件的电脑上,它将很多配置和服务直接帮你完成,简单好用容易上手。VisualSVN Server有三个版本,社区版免费但限15个用户,另有一般和‘企业’两个收费版本…

如何卸载ollama

文章目录 一 概述二 卸载2.1 Windows平台卸载 ollama2.2 Linux 平台卸载 ollama2.3 Docker 平台卸载 ollama 参考链接 一 概述 本文档主要讲述 ollama 如何卸载,适用范围包括 Windows Linux 以及 Docker 等平台的安装方式。 二 卸载 2.1 Windows平台卸载 ollama …

学习C++应该做点什么项目

C作为一门底层可操作性很强的语言,广泛应用于游戏开发、工业和追求性能、速度的应用。 比如腾讯,无论游戏,还是微信,整个鹅厂后台几乎都是 C 开发,对 C 开发者的需求非常大。 但问题是C入门和精通都比较困难&#xf…

有哪些挣钱软件一天能赚几十元?盘点十个能长期做下去的挣钱软件

在这个信息爆炸的时代,每个人都在寻找快速赚钱的秘诀。很多人做兼职副业的目标并不是获得很大的成功,大部分人一天能赚几十就心满意足了。 今天,我要带你一探究竟,揭秘那些能让你日赚几十元的挣钱软件。准备好了吗?让我…

单枪匹马月入17万美元:数字游民Pieter Levels如何成就商业传奇

了解数字游民的应该都听说过 Pieter Levels,可以说他是数字游民的先驱人物。 他在推特上拥有超过43万的粉丝,仅凭一台笔记本电脑就连续建立了多个高盈利网站,光是推特主页上展示的比较新的几个网站,每月收入加起来就高达 17.6 万…

Vulnhub项目:THE PLANETS: MERCURY

1、靶场地址 The Planets: Mercury ~ VulnHubThe Planets: Mercury, made by SirFlash. Download & walkthrough links are available.https://vulnhub.com/entry/the-planets-mercury,544/ 这好像是个系列的,关于星球系列,之前还做过一个地球的&a…

STM32-15-DMA

STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG STM32-10-定时器 STM32-11-电容触摸按键 STM32-12-OLED模块 STM32-13-MPU STM32-14-FSMC_LCD 文章目录 STM…

[原创][Delphi多线程]TThreadedQueue的经典使用案例.

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delph…