Heim > System-Tutorial > LINUX > Hauptteil

Linux CFS: So erreichen Sie vollständige Fairness bei der Prozessplanung

PHPz
Freigeben: 2024-02-12 09:30:13
nach vorne
504 Leute haben es durchsucht

Prozessplanung ist eine der Kernfunktionen des Betriebssystems. Sie bestimmt, welche Prozesse CPU-Ausführungszeit erhalten können und wie viel Zeit sie erhalten. In Linux-Systemen gibt es viele Prozessplanungsalgorithmen. Der wichtigste und am häufigsten verwendete ist der Completely Fair Scheduling Algorithm (CFS), der ab Linux Version 2.6.23 eingeführt wurde. Das Ziel von CFS besteht darin, jedem Prozess eine angemessene und faire Zuweisung von CPU-Zeit entsprechend seinem eigenen Gewicht und Bedarf zu ermöglichen und so die Gesamtleistung und Reaktionsgeschwindigkeit des Systems zu verbessern. In diesem Artikel werden die Grundprinzipien, die Datenstruktur, Implementierungsdetails sowie die Vor- und Nachteile von CFS vorgestellt und Ihnen dabei geholfen, die vollständige Fairness der Linux-Prozessplanung besser zu verstehen.

Eine kurze Geschichte des Linux-Schedulers

Frühe Linux-Scheduler verwendeten ein minimalistisches Design, das offensichtlich nicht auf große Architekturen mit vielen Prozessoren ausgerichtet war, geschweige denn auf Hyper-Threading. 1.2 Der Linux-Scheduler verwendet eine Ringwarteschlange für die Verwaltung ausführbarer Aufgaben und verwendet eine Round-Robin-Planungsstrategie. Dieser Scheduler fügt Prozesse sehr effizient hinzu und entfernt sie (mit Sperren, die die Struktur schützen). Kurz gesagt, der Scheduler ist nicht komplex, sondern einfach und schnell.
Linux Version 2.2 führte das Konzept der Planungsklassen ein und ermöglichte Planungsstrategien für Echtzeitaufgaben, nicht präemptive Aufgaben und Nicht-Echtzeitaufgaben. Der 2.2-Scheduler bietet außerdem Unterstützung für symmetrisches Multiprocessing (SMP).
Der 2.4-Kernel enthält einen relativ einfachen Scheduler, der in O(N)-Intervallen ausgeführt wird (er durchläuft jede Aufgabe während des Planungsereignisses). 2.4 Der Scheduler unterteilt die Zeit in Epochen. In jeder Epoche darf jede Aufgabe ausgeführt werden, bis ihre Zeitscheibe erschöpft ist. Wenn eine Aufgabe nicht alle Zeitscheiben nutzt, wird die Hälfte der verbleibenden Zeitscheiben zur neuen Zeitscheibe hinzugefügt, sodass sie in der nächsten Epoche länger ausgeführt werden kann. Der Scheduler iteriert einfach über Aufgaben und wendet eine Gütefunktion (Metrik) an, um zu entscheiden, welche Aufgabe als nächstes ausgeführt werden soll. Obwohl diese Methode relativ einfach ist, ist sie relativ ineffizient, nicht skalierbar und nicht für den Einsatz in Echtzeitsystemen geeignet. Es fehlt auch die Fähigkeit, die Vorteile neuer Hardware-Architekturen wie Multi-Core-Prozessoren zu nutzen.
Der frühe 2.6-Scheduler, genannt O(1)-Scheduler, wurde entwickelt, um ein Problem mit dem 2.4-Scheduler zu lösen – der Scheduler musste nicht die gesamte Aufgabenliste durchlaufen, um die nächste zu planende Aufgabe zu bestimmen (daher der Name O( 1), was bedeutet, dass es effizienter und skalierbarer ist. Der O(1)-Scheduler verfolgt die ausführbaren Aufgaben in der Ausführungswarteschlange (eigentlich gibt es zwei Ausführungswarteschlangen pro Prioritätsstufe – eine für aktive Aufgaben und eine für abgelaufene Aufgaben), was bedeutet, dass der Planer bestimmt, welche Aufgaben als nächste Aufgabe ausgeführt werden sollen Entnimmt einfach die nächste Aufgabe aus der Ausführungswarteschlange einer bestimmten Aktivität nach Priorität. Der O(1)-Scheduler lässt sich besser skalieren und bietet Interaktivität, wodurch eine Fülle von Erkenntnissen zur Bestimmung, ob eine Aufgabe E/A-gebunden oder prozessorgebunden ist, bereitgestellt wird. Aber der O(1)-Scheduler im Kernel ist ungeschickt. Die Berechnung von Offenbarungen erfordert viel Code, ist schwierig zu verwalten und erfasst für Puristen nicht das Wesentliche des Algorithmus.

Um die Probleme des O(1)-Schedulers zu lösen und mit anderen externen Belastungen umzugehen, muss etwas geändert werden. Diese Änderung stammt aus dem Kernel-Patch von Con Kolivas, der seinen Rotating Staircase Deadline Scheduler (RSDL) enthält, der seine frühen Arbeiten am Treppenplaner beinhaltet. Das Ergebnis dieser Arbeit ist ein einfach gestalteter Scheduler, der Fairness und begrenzte Latenz berücksichtigt. Der Scheduler von Kolivas hat viel Aufmerksamkeit erregt (und viele fordern, ihn in den aktuellen Mainstream-Kernel 2.6.21 aufzunehmen), und es ist klar, dass Änderungen am Scheduler bevorstehen. Ingo Molnar, der Erfinder des O(1)-Schedulers, entwickelte daraufhin einen CFS-basierten Scheduler auf der Grundlage einiger Ideen von Kolivas. Lassen Sie uns CFS genauer untersuchen und sehen, wie es auf hohem Niveau funktioniert.

———————————————————————————————————————

CFS-Übersicht

Die Hauptidee von CFS besteht darin, ein Gleichgewicht (Fairness) in Bezug auf die Bereitstellung von Prozessorzeit für Aufgaben aufrechtzuerhalten. Dies bedeutet, dass Prozessen eine erhebliche Anzahl von Prozessoren zugewiesen werden sollte. Wenn die einer Aufgabe zugewiesene Zeit nicht im Gleichgewicht ist (was bedeutet, dass einer oder mehreren Aufgaben im Vergleich zu anderen Aufgaben nicht viel Zeit eingeräumt wird), sollte der nicht im Gleichgewicht befindlichen Aufgabe Zeit zur Ausführung gegeben werden.

Um ein Gleichgewicht zu erreichen, verwaltet CFS die für eine Aufgabe bereitgestellte Zeit in einer sogenannten virtuellen Laufzeit. Je kleiner die virtuelle Laufzeit einer Aufgabe ist, desto kürzer ist die Zeit, die der Aufgabe erlaubt ist, auf den Server zuzugreifen – desto höher ist die Belastung des Prozessors. CFS beinhaltet auch das Konzept der Sleep-Fairness, um sicherzustellen, dass Aufgaben, die derzeit nicht ausgeführt werden (z. B. auf E/A warten), einen angemessenen Anteil des Prozessors erhalten, wenn sie ihn schließlich benötigen.

Aber im Gegensatz zu früheren Linux-Schedulern, die Aufgaben nicht in einer Ausführungswarteschlange verwalteten, verwaltete CFS einen zeitlich geordneten Rot-Schwarz-Baum (siehe Abbildung 1). Ein rotschwarzer Baum ist ein Baum mit vielen interessanten und nützlichen Eigenschaften. Erstens ist es selbstausgleichend, was bedeutet, dass kein Pfad im Baum mehr als doppelt so lang ist wie jeder andere Pfad. Zweitens erfolgt die Ausführung im Baum in O(log n) Zeit (wobei n die Anzahl der Knoten im Baum ist). Dadurch können Sie Aufgaben schnell und effizient einfügen oder löschen.

Abbildung 1. Beispiel eines rot-schwarzen Baumes
Linux CFS:如何实现进程调度的完全公平

Aufgaben werden in einem zeitlich geordneten rot-schwarzen Baum (dargestellt durch sched_entity Objekte) gespeichert, wobei die prozessorintensivsten Aufgaben (geringste virtuelle Laufzeit) auf der linken Seite des Baums und die prozessorintensivsten Aufgaben ( Die höchste virtuelle Laufzeit) wird auf der rechten Seite des Baums gespeichert. Aus Gründen der Fairness wählt der Planer dann den am weitesten links stehenden Knoten des rot-schwarzen Baums aus, der als nächstes geplant werden soll, um die Fairness aufrechtzuerhalten. Eine Aufgabe berücksichtigt ihre CPU-Zeit, indem sie ihre Laufzeit zur virtuellen Laufzeit hinzufügt und sie dann, sofern sie ausführbar ist, wieder in den Baum einfügt. Auf diese Weise wird den Aufgaben auf der linken Seite des Baums Zeit zum Ausführen gegeben, und der Inhalt des Baums wird von rechts nach links migriert, um die Fairness zu gewährleisten. Daher holt jede ausführbare Aufgabe andere Aufgaben ein, um die Ausführungsbalance über den gesamten Satz ausführbarer Aufgaben hinweg aufrechtzuerhalten.

———————————————————————————————————————

CFS-interne Prinzipien

Alle Aufgaben innerhalb von Linux sind organisiert nach task_structs Darstellung der Aufgabenstruktur. Diese Struktur (und andere verwandte Inhalte) beschreibt die Aufgabe vollständig und umfasst den aktuellen Status der Aufgabe, ihren Stapel, ihre Prozessidentität, ihre Priorität (statisch und dynamisch) usw. Sie finden diese und verwandte Strukturen in ./linux/include/linux/sched.h. Da aber nicht alle Aufgaben ausführbar sind, werden Sie, Menlo, monospace;color: #10f5d6c">task_struct keine CFS-bezogenen Felder finden. Stattdessen wird eine neue Struktur namens task_struct 的任务结构表示。该结构(以及其他相关内容)完整地描述了任务并包括了任务的当前状态、其堆栈、进程标识、优先级(静态和动态)等等。您可以在 ./linux/include/linux/sched.h 中找到这些内容以及相关结构。 但是因为不是所有任务都是可运行的,您在 task_struct 中不会发现任何与 CFS 相关的字段。 相反,会创建一个名为 sched_entity erstellt, um Planungsinformationen zu verfolgen (siehe Abbildung 2).

Abbildung 2. Strukturelle Hierarchie von Aufgaben und rot-schwarzen Bäumen
Linux CFS:如何实现进程调度的完全公平

Die Beziehung zwischen verschiedenen Strukturen ist in Abbildung 2 dargestellt. Die Wurzel des Baumes verläuft durch die rb_root 元素通过 cfs_rq 结构(在 ./kernel/sched.c 中)引用。红黑树的叶子不包含信息,但是内部节点代表一个或多个可运行的任务。红黑树的每个节点都由 rb_node 表示,它只包含子引用和父对象的颜色。 rb_node 包含在sched_entity 结构中,该结构包含 rb_node 引用、负载权重以及各种统计数据。最重要的是, sched_entity 包含 vruntime(64 位字段),它表示任务运行的时间量,并作为红黑树的索引。 最后,task_struct 位于顶端,它完整地描述任务并包含 sched_entity-Struktur.

Was den CFS-Teil betrifft, ist die Planungsfunktion sehr einfach. In ./kernel/sched.c sehen Sie die generische schedule() 函数,它会先抢占当前运行任务(除非它通过yield() 代码先抢占自己)。注意 CFS 没有真正的时间切片概念用于抢占,因为抢占时间是可变的。 当前运行任务(现在被抢占的任务)通过对 put_prev_task 调用(通过调度类)返回到红黑树。 当 schedule 函数开始确定下一个要调度的任务时,它会调用 pick_next_task函数。此函数也是通用的(在 ./kernel/sched.c 中),但它会通过调度器类调用 CFS 调度器。 CFS 中的 pick_next_task 函数可以在 ./kernel/sched_fair.c(称为 pick_next_task_fair())中找到。 此函数只是从红黑树中获取最左端的任务并返回相关 sched_entity。通过此引用,一个简单的 task_of() 调用确定返回的 task_struct-Referenz. Der Universal Scheduler stellt schließlich den Prozessor für diese Aufgabe bereit.

———————————————————————————————————————

Priorität und CFS

CFS verwendet die Priorität nicht direkt, sondern als Abklingfaktor für die Zeit, die eine Aufgabe ausführen darf. Aufgaben mit niedriger Priorität haben einen höheren Abklingkoeffizienten, während Aufgaben mit hoher Priorität einen niedrigeren Abklingkoeffizienten haben. Dies bedeutet, dass die für die Aufgabenausführung vorgesehene Zeit bei Aufgaben mit niedriger Priorität schneller verbraucht wird als bei Aufgaben mit hoher Priorität. Dies ist eine praktische Lösung, um die Aufrechterhaltung einer nach Priorität geplanten Ausführungswarteschlange zu vermeiden.

CFS-Gruppenplanung

Ein weiterer interessanter Aspekt von CFS ist das Gruppenplanungskonzept (eingeführt im Kernel 2.6.24). Die Gruppenplanung ist eine weitere Möglichkeit, die Planung fairer zu gestalten, insbesondere wenn es um Aufgaben geht, die viele andere Aufgaben nach sich ziehen. Angenommen, ein Server, der viele Aufgaben auslöst, möchte eingehende Verbindungen parallelisieren (eine typische Architektur für HTTP-Server). Nicht alle Aufgaben werden einheitlich und fair behandelt, und CFS führt Gruppen ein, um mit diesem Verhalten umzugehen. Die Serverprozesse, die Aufgaben erzeugen, teilen ihre virtuellen Laufzeiten innerhalb der Gruppe (in einer Hierarchie), während einzelne Aufgaben ihre eigenen unabhängigen virtuellen Laufzeiten verwalten. Auf diese Weise erhalten einzelne Aufgaben ungefähr die gleiche Planungszeit wie die Gruppe. Sie werden feststellen, dass die /proc-Schnittstelle zum Verwalten der Prozesshierarchie verwendet wird, sodass Sie die vollständige Kontrolle darüber haben, wie Gruppen gebildet werden. Mit dieser Konfiguration können Sie Fairness auf Benutzer, Prozesse oder Variationen davon verteilen.

Kurse und Domänen planen

Zusammen mit CFS wurde das Konzept der Unterrichtsplanung eingeführt (siehe Abbildung 2). Jede Aufgabe gehört zu einer Planungsklasse, die bestimmt, wie die Aufgabe geplant wird. Die Scheduling-Klasse definiert einen allgemeinen Satz von Funktionen (über sched_class),函数集定义调度器的行为。例如,每个调度器提供一种方式, 添加要调度的任务、调出要运行的下一个任务、提供给调度器等等。每个调度器类都在一对一连接的列表中彼此相连,使类可以迭代(例如, 要启用给定处理器的禁用)。一般结构如图 3 所示。注意,将任务函数加入队列或脱离队列只需从特定调度结构中加入或移除任务。 函数 pick_next_task, um die nächste auszuführende Aufgabe auszuwählen (abhängig von der spezifischen Strategie der Scheduling-Klasse).

Abbildung 3. Grafische Ansicht der Planung
Linux CFS:如何实现进程调度的完全公平

Aber vergessen Sie nicht, dass die Scheduling-Klasse Teil der Aufgabenstruktur selbst ist (siehe Abbildung 2). Dies vereinfacht die Bedienung von Aufgaben unabhängig von ihrer Planungsklasse. Beispielsweise setzt die folgende Funktion die aktuell laufende Aufgabe (wobei curr 定义了当前运行任务, rq 代表 CFS 红黑树而 p die nächste zu planende Aufgabe ist) durch eine neue Aufgabe in ./kernel/sched.c vorweg:

static inline void check_preempt( struct rq *rq, struct task_struct *p )
{
  rq->curr->sched_class->check_preempt_curr( rq, p );
}
Nach dem Login kopieren

Wenn diese Aufgabe die Fair Scheduling-Klasse verwendet, dann check_preempt_curr() 将解析为 check_preempt_wakeup(). Sie können diese Beziehungen in ./kernel/sched_rt.c, ./kernel/sched_fair.c und ./kernel/sched_idle.c anzeigen.

Scheduling-Klassen sind ein weiterer interessanter Ort, an dem sich die Terminplanung ändert, aber mit zunehmender Planungsdomäne wächst auch die Funktionalität. Mit diesen Domänen können Sie einen oder mehrere Prozessoren für Lastausgleichs- und Isolationszwecke hierarchisch gruppieren. Ein oder mehrere Prozessoren können eine Planungsrichtlinie gemeinsam nutzen (und den Lastausgleich zwischen ihnen aufrechterhalten) oder unabhängige Planungsrichtlinien implementieren, um Aufgaben absichtlich zu isolieren.

Andere Planer

Wenn Sie sich weiter mit der Planung befassen, werden Sie feststellen, dass sich in der Entwicklung befindliche Planer befinden, die die Grenzen von Leistung und Skalierbarkeit erweitern. Unbeeindruckt von seiner Linux-Erfahrung entwickelte Con Kolivas einen weiteren Linux-Scheduler, abgekürzt: BFS. Der Scheduler soll auf NUMA-Systemen und Mobilgeräten eine bessere Leistung haben und wurde in einer Ableitung des Android-Betriebssystems eingeführt.

Durch diesen Artikel sollten Sie über ein grundlegendes Verständnis von CFS verfügen. Es handelt sich um einen der fortschrittlichsten und effizientesten Prozessplanungsalgorithmen in Linux-Systemen. Er verwendet Rot-Schwarz-Bäume, um ausführbare Prozesswarteschlangen zu speichern und die virtuelle Laufzeit zu berechnen Fairness des Prozesses: Die Reaktionsgeschwindigkeit des interaktiven Prozesses wird durch die Implementierung der Wake-up-Preemption-Funktion verbessert, wodurch vollständige Fairness bei der Prozessplanung erreicht wird. Natürlich ist CFS nicht perfekt und weist einige potenzielle Probleme und Einschränkungen auf, die behoben werden müssen, z. B. eine Überkompensation aktiver Schlafprozesse, eine unzureichende Unterstützung von Echtzeitprozessen usw zukünftige Versionen. Nehmen Sie Verbesserungen und Optimierungen vor. Kurz gesagt, CFS ist eine unverzichtbare Komponente im Linux-System und verdient Ihr gründliches Studium und Ihre Beherrschung.

Das obige ist der detaillierte Inhalt vonLinux CFS: So erreichen Sie vollständige Fairness bei der Prozessplanung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:lxlinux.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!