Ein Tag, um den stereotypen Aufsatz des Betriebssysteminterviews zu verstehen

Der Inhalt stammt von meiner Lernwebsite: topjavaer.cn

Vier Merkmale eines Betriebssystems?

Parallelität: Ausführung mehrerer Programme innerhalb desselben Zeitraums (im Gegensatz zur Parallelität bezieht sich Parallelität auf mehrere Ereignisse gleichzeitig, Multiprozessorsysteme können dafür sorgen, dass Programme parallel ausgeführt werden)

Gemeinsame Nutzung: Ressourcen im System können von mehreren gleichzeitig ausgeführten Threads im Speicher gemeinsam genutzt werden

Virtuell: Virtualisieren Sie eine physische Einheit in mehrere

Asynchron: Der Systemprozess wird im Stop-and-Go-Verfahren (nicht auf einmal) ausgeführt und es ist nicht vorhersehbar, wann und wie schnell der Prozess voranschreitet

Prozessthread

Ein Prozess bezieht sich auf ein Anwendungsprogramm, das im Speicher ausgeführt wird, und jeder Prozess verfügt über seinen eigenen unabhängigen Speicherbereich.

Ein Thread ist eine Ausführungseinheit, die kleiner als ein Prozess ist. Es handelt sich um einen unabhängigen Kontrollfluss in einem Prozess. Ein Prozess kann mehrere Threads starten und jeder Thread führt verschiedene Aufgaben parallel aus.

Der Unterschied zwischen Prozess und Thread ist wie folgt :

  • Planung: Der Prozess ist die Grundeinheit der Ressourcenverwaltung, und der Thread ist die Grundeinheit der Programmausführung.
  • Wechseln: Der Thread-Kontextwechsel ist viel schneller als der Prozesskontextwechsel.
  • Ressourcen besitzen: Ein Prozess ist eine unabhängige Einheit, die Ressourcen besitzt. Threads besitzen keine Systemressourcen, können aber auf Ressourcen zugreifen, die zu Prozessen gehören.
  • System-Overhead: Beim Erstellen oder Abbrechen eines Prozesses muss das System ihm Systemressourcen wie Speicherplatz, E/A-Geräte usw. zuweisen oder zurückfordern. Der vom Betriebssystem gezahlte Overhead ist deutlich größer als der Overhead beim Erstellen oder Abbrechen von Threads Und der Overhead des Prozesswechsels ist auch viel größer als der Overhead des Threadwechsels.

Dieser Artikel wurde in das Github-Warehouse aufgenommen, das Computer Foundation, Java Foundation, Multithreading, JVM, Datenbank, Redis, Spring, Mybatis, SpringMVC, SpringBoot, verteilt, Microservices, Designmuster, Architektur, Schulrekrutierung und Social-Recruiting-Sharing umfasst. usw. Kernwissenspunkte, willkommen bei star~

Github-Adresse

Wenn Sie keinen Zugriff auf Github haben, können Sie auf die Gitee-Adresse zugreifen.

Adresse des Ferienhauses

Parallelität und Parallelität

Parallelität bedeutet, dass mehrere Aufgaben innerhalb eines bestimmten Zeitraums verarbeitet werden, zu einem bestimmten Zeitpunkt jedoch nur eine Aufgabe ausgeführt wird. Single-Core-Prozessoren können gleichzeitig arbeiten. Es gibt beispielsweise zwei Prozesse , Adie nach der Ausführung einer Zeitscheibe zu wechseln und nach der Ausführung einer Zeitscheibe zu wechseln . Da die Umschaltgeschwindigkeit schnell genug ist, wird makroskopisch gezeigt, dass über einen bestimmten Zeitraum hinweg mehrere Programme gleichzeitig ausgeführt werden können. Die umfassendste Java-InterviewseiteBABBA

Parallelität bedeutet, dass mehrere Aufgaben gleichzeitig ausgeführt werden. Dies erfordert einen Multi-Core-Prozessor. Auf Mikroebene können mehrere Anweisungen gleichzeitig ausgeführt werden. Verschiedene Programme werden auf verschiedenen Prozessoren ausgeführt. Dies sind physikalisch mehrere Prozesse gleichzeitig.

Vorteile von Multithreading gegenüber Single-Threading

1. Parallelität verbessert die Effizienz der Programmausführung

2. Verbessern Sie die CPU-Auslastung und Sie können beim Zugriff auf den Speicher die auszuführenden Threads wechseln

3. Schnellere Antwortgeschwindigkeit, Sie können einen dedizierten Thread zur Überwachung von Benutzeranfragen und einen dedizierten Thread zur Verarbeitung von Anfragen haben. Beispielsweise sind der Überwachungsthread und der Arbeitsthread zwei Threads, sodass der Überwachungsthread für die Überwachung und der Worker für die Arbeit verantwortlich ist. Wenn eine Benutzeranforderung erkannt wird, wird die Anforderung sofort zur Verarbeitung an den Arbeitsthread übertragen , und der Überwachungsthread überwacht weiterhin.

Was ist eine Coroutine?

Eine Coroutine ist ein leichter Thread im Benutzermodus.

Die Coroutine wird nicht vom Betriebssystemkernel verwaltet, sondern vollständig vom Benutzerprogramm gesteuert. Dies hat den Vorteil, dass die Leistung erheblich verbessert wird und keine Ressourcen wie Thread-Switching verbraucht werden.

Eine Coroutine kann als eine Funktion verstanden werden, die die Ausführung unterbrechen kann. Es verfügt über einen eigenen Registerkontext und Stapel. Wenn der Coroutine-Zeitplan umgeschaltet wird, werden der Registerkontext und der Stapel an anderen Orten gespeichert. Beim Zurückschalten werden der zuvor gespeicherte Registerkontext und der Stapel wiederhergestellt. Es gibt grundsätzlich keinen Kernel-Umschaltaufwand für den direkten Betrieb des Stapels, und globale Variablen können dies tun Der Zugriff erfolgt ohne Sperrung, sodass der Kontextwechsel sehr schnell erfolgt.

Was ist der Unterschied zwischen Threads und Coroutinen?

1. Threads sind präventiv, während Coroutinen nicht präemptiv sind. Daher muss der Benutzer das Nutzungsrecht freigeben, um zu anderen Coroutinen zu wechseln. Daher hat nur eine Coroutine das Recht, gleichzeitig ausgeführt zu werden, was der Fähigkeit von entspricht ein einzelner Thread.
2. Threads sind Ressourcen von Coroutinen. Coroutinen nutzen Thread-Ressourcen indirekt über den Executor (Interceptor), der jedem Thread oder Thread-Pool zugeordnet werden kann.

Prozesskommunikation

Es gibt verschiedene Möglichkeiten, zwischen Prozessen zu kommunizieren:

1. Pipeline-Kommunikation

Anonyme Pipe (Pipe): Pipe ist eine Halbduplex-Kommunikationsmethode, Daten können nur in eine Richtung fließen und nur zwischen verwandten Prozessen verwendet werden. Prozessaffinität bezieht sich normalerweise auf die Eltern-Kind-Prozessbeziehung.
Die bekannte Pipe ist eine Halbduplex-Kommunikationsmethode, bei der Daten nur in eine Richtung fließen können.

2. Nachrichtenwarteschlange

3. Gemeinsamer Speicher . Shared Memory ist die schnellste IPC-Methode und wurde speziell dafür entwickelt, ineffizient zu laufen, wenn andere Methoden der Interprozesskommunikation ausgeführt werden. Es wird häufig in Verbindung mit anderen Kommunikationsmechanismen wie Semaphoren verwendet, um eine Synchronisierung und Kommunikation zwischen Prozessen zu erreichen.

4. Semaphor . Ein Semaphor ist ein Zähler, mit dem der Zugriff mehrerer Prozesse auf gemeinsam genutzte Ressourcen gesteuert werden kann. Es wird häufig als Sperrmechanismus verwendet, um zu verhindern, dass andere Prozesse auf gemeinsam genutzte Ressourcen zugreifen, während ein Prozess auf die Ressource zugreift. Daher wird es hauptsächlich als Mittel zur Synchronisierung zwischen Prozessen und zwischen verschiedenen Threads im selben Prozess verwendet.

Was ist Deadlock?

Deadlock bezieht sich auf ein Phänomen, bei dem zwei oder mehr Threads aufgrund der Konkurrenz um Ressourcen während der Ausführung aufeinander warten. Ohne äußere Kraft können sie nicht vorankommen.

Wie in der folgenden Abbildung gezeigt, enthält Thread A Ressource 2 und Thread B enthält Ressource 1. Beide möchten gleichzeitig die von der anderen Partei gehaltene Ressource beantragen, sodass die beiden Threads aufeinander warten und a eingeben Deadlock-Zustand.

[Externer Link-Bildtransfer fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Diebstahl-Link-Mechanismus, es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-Yhm3UpHS-1688478183644)(http://img.topjavaer.cn/img/ deadlock.png)]

Das folgende Beispiel veranschaulicht den Thread-Deadlock und der Code stammt aus der Schönheit der gleichzeitigen Programmierung.

public class DeadLockDemo {
    
    
    private static Object resource1 = new Object();//资源 1
    private static Object resource2 = new Object();//资源 2

    public static void main(String[] args) {
    
    
        new Thread(() -> {
    
    
            synchronized (resource1) {
    
    
                System.out.println(Thread.currentThread() + "get resource1");
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource2");
                synchronized (resource2) {
    
    
                    System.out.println(Thread.currentThread() + "get resource2");
                }
            }
        }, "线程 1").start();

        new Thread(() -> {
    
    
            synchronized (resource2) {
    
    
                System.out.println(Thread.currentThread() + "get resource2");
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource1");
                synchronized (resource1) {
    
    
                    System.out.println(Thread.currentThread() + "get resource1");
                }
            }
        }, "线程 2").start();
    }
}

Die Codeausgabe lautet wie folgt:

Thread[线程 1,5,main]get resource1
Thread[线程 2,5,main]get resource2
Thread[线程 1,5,main]waiting get resource2
Thread[线程 2,5,main]waiting get resource1

Thread A erwirbt die Monitorsperre für Ressource1 über synchronized(Ressource1) und übergibt Thread.sleep(1000). Lassen Sie Thread A 1 Sekunde lang ruhen, damit Thread B ausgeführt werden kann, und erhalten Sie dann die Monitorsperre von Ressource2. Nachdem der Ruhezustand von Thread A und Thread B beendet ist, beginnen beide, die Ressourcen der anderen Partei anzufordern, und dann geraten die beiden Threads in einen Zustand des gegenseitigen Wartens, was zu einem Deadlock führt.

Wie kommt es zum Deadlock? Wie kann man es vermeiden?

Vier notwendige Bedingungen für das Auftreten eines Deadlocks :

  • Gegenseitiger Ausschluss: Eine Ressource kann jeweils nur von einem Prozess genutzt werden

  • Anfordern und Halten: Wenn ein Prozess aufgrund der Anforderung von Ressourcen blockiert wird, werden die erhaltenen Ressourcen nicht freigegeben

  • Kein Entzug: Die durch den Prozess gewonnenen Ressourcen können nicht gewaltsam entzogen werden, bevor sie verwendet werden

  • Zirkuläres Warten: zyklisches Warten auf Ressourcen zwischen Prozessen

Möglichkeiten, einen Deadlock zu vermeiden :

  • Gegenseitige Ausschlussbedingungen können nicht zerstört werden, da Sperren den gegenseitigen Ausschluss gewährleisten sollen
  • Beantragen Sie alle Ressourcen gleichzeitig und vermeiden Sie, dass Threads Ressourcen belegen und auf andere Ressourcen warten
  • Wenn ein Thread, der einige Ressourcen belegt, weitere Ressourcen beantragt und die Anwendung nicht abgerufen werden kann, gibt sie die von ihr belegten Ressourcen aktiv frei
  • Beantragen Sie die Ressourcen nacheinander

Welche Prozessplanungsstrategien gibt es?

  • Wer zuerst kommt, mahlt zuerst : Nicht präemptiver Planungsalgorithmus, Planung entsprechend der Reihenfolge der Anforderungen. Es ist gut für lange Jobs, aber nicht für kurze Jobs, da kurze Jobs auf die Ausführung der vorherigen langen Jobs warten müssen, bevor sie ausgeführt werden können, und lange Jobs müssen lange ausgeführt werden, was dazu führt zu lange Wartezeit für kurze Aufträge. Darüber hinaus eignet es sich nicht für I/Ointensive Prozesse, da solche Prozesse I/Onach jedem Vorgang erneut in die Warteschlange gestellt werden müssen.

  • Kürzester Job zuerst : Ein nicht präemptiver Planungsalgorithmus, der in der Reihenfolge mit der kürzesten geschätzten Laufzeit plant. Langfristige Aufträge können verhungern und darauf warten, dass kurze Aufträge erledigt werden. Denn wenn weiterhin kurze Jobs kommen, werden lange Jobs nie eingeplant.

  • Kürzeste verbleibende Zeit zuerst : Eine präventive Version des kürzesten Jobs zuerst, geplant in der Reihenfolge der verbleibenden Laufzeit. Wenn ein neuer Job eintrifft, wird seine Gesamtlaufzeit mit der verbleibenden Zeit des aktuellen Prozesses verglichen. Wenn der neue Prozess weniger Zeit benötigt, unterbrechen Sie den aktuellen Prozess und führen Sie den neuen Prozess aus. Ansonsten wartet der neue Prozess.

  • Zeitscheibenrotation : Ordnen Sie alle bereiten Prozesse FCFSnach dem Prinzip von in einer Warteschlange an und weisen Sie CPUdem Warteschlangenleiterprozess bei jeder Planung Zeit zu, und dieser Prozess kann eine Zeitscheibe ausführen. Wenn die Zeitscheibe aufgebraucht ist, sendet der Timer einen Takt-Interrupt, und der Scheduler stoppt die Ausführung des Prozesses und sendet ihn an das Ende der Bereitschaftswarteschlange, während er dem Prozess an der Spitze der Warteschlange weiterhin Zeit zuweist CPU.

    Die Effizienz des Zeitscheibenrotationsalgorithmus hat viel mit der Größe der Zeitscheibe zu tun: Da die Prozessumschaltung die Prozessinformationen speichern und die Informationen des neuen Prozesses laden muss, wird die Prozessumschaltung durchgeführt, wenn die Zeitscheibe zu klein ist zu häufig sein. würde zu viel Zeit in Anspruch nehmen. Und wenn die Zeitscheibe zu lang ist, kann die Echtzeitleistung nicht garantiert werden.

  • Prioritätsplanung : Weisen Sie jedem Prozess eine Priorität zu und planen Sie entsprechend der Priorität. Um zu verhindern, dass Prozesse mit niedriger Priorität nie auf ihre Planung warten, kann die Priorität wartender Prozesse im Laufe der Zeit erhöht werden.

Was sind die Zustände eines Prozesses?

Ein Prozess hat insgesamt 5drei Zustände, nämlich Erstellung, Bereit, Laufen (Ausführung), Beendigung und Blockierung.

  • Der Ausführungsstatus bedeutet, dass der Prozess CPUdarauf ausgeführt wird. In einer Einprozessorumgebung wird jeweils höchstens ein Prozess ausgeführt.
  • Der Status „Bereit“ bedeutet, dass sich der Prozess bereits im Zustand „Bereit zur Ausführung“ befindet, d. h. der Prozess hat CPUalle erforderlichen Ressourcen mit Ausnahme der Ressource erhalten und CPUkann nach Erhalt ausgeführt werden.
  • Ein blockierter Zustand liegt vor, wenn ein Prozess angehalten wird, während er auf ein Ereignis wartet, beispielsweise darauf, dass eine Ressource verfügbar wird oder abgeschlossen wird I/O. Auch im CPULeerlauf kann der Prozess nicht ausgeführt werden.

Ausführungsstatus → Blockierungsstatus : Dies wird häufig durch Warten auf Peripheriegeräte, Warten auf Ressourcenzuweisung wie Hauptspeicher oder Warten auf manuelle Eingriffe verursacht.
Blockierter Zustand→Bereitschaftszustand : Die Wartebedingung wurde erfüllt und kann ausgeführt werden, nachdem er dem Prozessor zugewiesen wurde.
Laufzustand→Bereitschaftszustand : Es liegt nicht an seinen eigenen Gründen, sondern an externen Gründen, dass der Prozess im laufenden Zustand den Prozessor aufgibt und dann in den Bereitschaftszustand übergeht. Beispielsweise ist die Zeitscheibe aufgebraucht oder es gibt einen Prozess mit höherer Priorität, der dem Prozessor zuvorkommt usw.
Bereitstatus → Ausführungsstatus : Das System wählt einen Prozess in der Bereitschaftswarteschlange aus, um den Prozessor gemäß einer bestimmten Strategie zu belegen, und wechselt zu diesem Zeitpunkt in den Ausführungsstatus.

Wie ist die Speicherfragmentierung im Betriebssystem zu verstehen?

Die Speicherfragmentierung wird normalerweise in interne Fragmentierung und externe Fragmentierung unterteilt:

  1. Interne Fragmentierung ist auf die Verwendung von Speicherpartitionen fester Größe zurückzuführen. Interne Fragmentierung tritt auf, wenn ein Prozess den ihm zugewiesenen festen Speicherbereich nicht vollständig nutzen kann. Normalerweise ist es schwierig, innere Ablagerungen vollständig zu vermeiden
  2. Bei der externen Fragmentierung handelt es sich um einen Speicherbereich, der von einem Prozess nicht genutzt werden kann, da ein nicht zugewiesener kontinuierlicher Speicherbereich zu klein ist, um die Speicherzuweisungsanforderung eines Prozesses zu erfüllen.

Was ist die Lösung ?

Die häufig verwendete Speicherzuweisungsmethode ist die Segmentseitenspeicherzuweisung. Teilen Sie den Speicher in Segmente und jedes Segment in Seiten fester Größe auf. Durch den Seitentabellenmechanismus müssen sich die Seiten im Segment nicht kontinuierlich im selben Speicherbereich befinden.

Virtueller Speicher

Der virtuelle Speicher ist ein Speichersystem mit der Funktion, eine Übertragung anzufordern und die Speicherkapazität logisch zu erweitern. Der virtuelle Speicher weist drei Merkmale auf: Multiplizität, Austauschbarkeit und Virtualität. Er kann Programme mehrfach übertragen. Der Speicher ermöglicht die Ausführung größerer Benutzerprogramme ein kleinerer Benutzerraum, sodass mehr Prozesse gleichzeitig ausgeführt werden können, wodurch der Systemdurchsatz verbessert wird. Wenn ein Seitenfehler auftritt, kann je nach Speicherverwaltung entweder ein Segment oder eine Seite geladen werden. Unter Virtualität versteht man die Abbildung von virtuellem Speicher und physischem Speicher.

Unter Linux kann der Prozess die physische Adresse des Speichers nicht direkt lesen und schreiben, sondern nur auf die [virtuelle Speicheradresse] zugreifen. Das Betriebssystem gibt die virtuelle Speicheradresse -> physische Adresse ein.

Der virtuelle Speicher löst das Problem, größere Anwendungen mit begrenztem Speicherplatz zu laden und Daten je nach Bedarf zwischen Speicher und Festplatte hin und her zu verschieben.

Durch die Form der Segmentseitentabelle wird ein kontinuierlicher Speicherplatz im virtuellen Speicher dem Hauptspeicher zugeordnet, und die Programmsegmente im Hauptspeicherraum sind möglicherweise nicht kontinuierlich.

Was ist Paginierung?

Teilen Sie den Speicherplatz in Blöcke gleicher Größe und fester Größe als Grundeinheit des Hauptspeichers auf. Da die Programmdaten auf verschiedenen Seiten gespeichert sind und die Seiten diskret im Speicher verteilt sind, ist eine Seitentabelle erforderlich, um die Zuordnungsbeziehung aufzuzeichnen und die Zuordnung von der Seitennummer zur physischen Blocknummer zu realisieren.

Der Zugriff auf die Speicherdaten im Paging-System erfordert zwei Speicherzugriffe (einer besteht darin, auf die Seitentabelle aus dem Speicher zuzugreifen, die angegebene physische Blocknummer daraus zu finden und den Offset in der Seite hinzuzufügen, um die tatsächliche physische Adresse zu erhalten; der zweite besteht darin, auf die Seitentabelle aus dem Speicher zuzugreifen, die angegebene physische Blocknummer daraus zu finden und den Offset in der Seite hinzuzufügen, um die tatsächliche physische Adresse zu erhalten Um die tatsächliche physische Adresse zu erhalten, greifen Sie beim ersten Mal auf die physische Adresse des Speichers zu, um Daten abzurufen.

Was ist Segmentierung?

Paging soll die Speichernutzung verbessern, und Segmentierung soll einige logische Anforderungen von Programmierern beim Schreiben von Code erfüllen (z. B. Datenfreigabe, Datenschutz, dynamische Verknüpfung usw.).

Bei der segmentierten Speicherverwaltung ist die Adresse zweidimensional, eindimensional ist die Segmentnummer und zweidimensional ist die Adresse innerhalb des Segments; die Länge jedes Segments ist unterschiedlich und die Adressierung jedes Segments beginnt bei 0 . Bei der Segmentverwaltung wird jedem Segment kontinuierlicher Speicher zugewiesen, die Segmente werden jedoch diskret zugewiesen, sodass auch eine Zuordnungsbeziehung zwischen logischen Adressen und physischen Adressen besteht, die dem Segmenttabellenmechanismus entspricht.

Was ist der Unterschied zwischen Paging und Segmentierung?

  • Das Paging ist für den Programmierer transparent, die Segmentierung erfordert jedoch, dass der Programmierer jedes Segment explizit unterteilt.
  • Der Adressraum des Paging ist ein eindimensionaler Adressraum und die Segmentierung ist zweidimensional.
  • Die Seitengröße ist unveränderlich und die Segmentgröße kann dynamisch geändert werden.
  • Paging wird hauptsächlich verwendet, um virtuellen Speicher zu implementieren, um einen größeren Adressraum zu erhalten. Die Segmentierung dient hauptsächlich dazu, die Aufteilung von Programmen und Daten in logisch unabhängige Adressräume zu ermöglichen und die gemeinsame Nutzung und den Schutz zu erleichtern.

Seitenersetzungsalgorithmus

Warum Seitenersetzung:

Da das Anwendungsprogramm mehrmals in den Speicher geladen wird, tritt nach einer bestimmten Laufzeit mit Sicherheit ein Seitenfehler auf. Wenn während des Adresszuordnungsprozesses festgestellt wird, dass sich die Seite, auf die zugegriffen werden soll, nicht im Speicher befindet, wird ein Seitenfehler-Interrupt generiert. Zu diesem Zeitpunkt muss das Betriebssystem eine Seite im Speicher auswählen, um sie aus dem Speicher zu verschieben und Platz für die zu übertragende Seite zu schaffen. Die Regel für die Auswahl der zu entfernenden Seite ist der Seitenersetzungsalgorithmus

Mehrere Algorithmen zum Ersetzen von Seiten:

Optimaler Ersetzungsalgorithmus (ideal) : Ersetzen Sie Seiten, auf die auf der aktuellen Seite für die längste Zeit in der Zukunft nicht zugegriffen wird

First in, first out : Eliminiert die Seite, die zuerst geladen wurde

LRU wurde am längsten nicht verwendet : Jede Seite verfügt über ein t, um den letzten Zugriff auf die Seite aufzuzeichnen, und die Seite mit dem größten t-Wert wird jedes Mal ersetzt, wenn sie ersetzt wird (implementiert durch Register oder Stapel).

Clock-Algorithmus Clock (auch als kürzlich nicht verwendeter Algorithmus NRU bekannt): Die Seite wird auf den Zugriff eingestellt und die Seiten werden zu einer kreisförmigen Liste verknüpft. Jede Seite hat ein Zugriffsbit 0/1. 1 bedeutet, dass im nächsten Zyklus eine weitere Chance besteht, gerettet zu werden Wenn der Zeiger darauf zeigt, kann diese Ersetzung ausgenommen werden, aber die Zugriffsposition wird auf 0 gesetzt, was bedeutet, dass sie ersetzt werden sollte, wenn sie das nächste Mal auf einen Schleifenzeiger trifft. Das Zugriffsbit wird beim Zugriff auf die Seite auf 1 gesetzt. Wenn beim Ersetzen der Seite das Zugriffsbit des aktuellen Zeigers 0 ist, ersetzen Sie es, andernfalls setzen Sie diesen Wert auf 0 und führen eine Schleife durch, bis die Seite mit dem Zugriffsbit 0 gefunden wird.

Verbesserter Taktalgorithmus : Fügen Sie dem Taktalgorithmus ein Modifikationsbit hinzu. Ersetzen Sie zunächst Seiten, wobei sowohl das Zugriffsbit als auch das Modifikationsbit auf 0 stehen, und ersetzen Sie dann Seiten mit dem Zugriffsbit auf 0 und dem Modifikationsbit auf 1.

Am wenigsten verwendeter Algorithmus LFU : Stellen Sie das Register so ein, dass es die Anzahl der Seitenbesuche aufzeichnet, und ersetzen Sie jedes Mal das Register mit der geringsten Anzahl aktueller Besuche.

Benutzermodus und Kernelmodus

Kernel-Modus: Die CPU kann auf alle Daten im Speicher zugreifen, auch auf Peripheriegeräte wie Festplatten, Netzwerkkarten, und die CPU kann auch selbst von einem Programm auf ein anderes umschalten.

Benutzermodus: Nur eingeschränkter Zugriff auf den Speicher und kein Zugriff auf Peripheriegeräte, die Fähigkeit, die CPU zu belegen, ist entzogen und CPU-Ressourcen können von anderen Programmen abgerufen werden.

Der größte Unterschied besteht darin, dass die Berechtigungen unterschiedlich sind. Programme, die im Benutzermodus ausgeführt werden, können nicht direkt auf die Datenstrukturen und Programme des Betriebssystemkernels zugreifen.

Warum gibt es diese beiden Staaten?

Der Kernel ist schnell, verfügt aber nur über begrenzte Ressourcen und es gibt nicht viele kontrollierbare Prozesse. Daher benötigt er die Unterstützung eines langsameren Benutzermodus. Um jedoch zu verhindern, dass der Benutzermodus böswillig verwendet wird, sind die Berechtigungen des Benutzers erforderlich Modusprogramme sind begrenzt.

Es ist notwendig, den Zugriff zwischen verschiedenen Programmen einzuschränken, um zu verhindern, dass sie Speicherdaten anderer Programme oder Daten von Peripheriegeräten abrufen und an das Netzwerk senden. Die CPU ist in zwei Berechtigungsstufen unterteilt: Benutzermodus und Kernelmodus .

wann man konvertieren muss

1. Systemaufruf :

Vom Benutzerprozess initiiert. Der Benutzermodusprozess fordert die Verwendung des vom Betriebssystem bereitgestellten Dienstprogramms an, um die Arbeit über den Systemaufruf abzuschließen. Beispielsweise dient fork () dazu, einen Systemaufruf auszuführen, um einen neuen Prozess zu erstellen.

Das Benutzerprogramm verwendet den Systemaufruf, der Systemaufruf wird in den Kernelmodus konvertiert und ruft das Betriebssystem auf

2. Eine Ausnahme tritt auf :

Es wechselt vom aktuell ausgeführten Prozess zum Kernel-bezogenen Programm, das diese Ausnahme behandelt

3. Unterbrechung der Peripheriegeräte:

Alle Programme laufen im Benutzermodus, aber beim Lesen von Daten von der Festplatte oder bei der Eingabe über die Tastatur kann nur das Betriebssystem diese Dinge tun, und das Programm muss das Betriebssystem auffordern, diese Vorgänge im Namen des Programms auszuführen . Zu diesem Zeitpunkt wechselt das Benutzermodusprogramm in den Kernelmodus.

Was ist ein Pufferüberlauf? Was ist der Schaden?

Pufferüberlauf bedeutet, dass, wenn der Computer den Puffer mit Daten füllt, die über die Kapazität des Puffers selbst hinausgehen, die übergelaufenen Daten die zulässigen Daten überschreiben.

Es gibt zwei Gefahren:

  • Programmabstürze führen zu einem Denial-of-Service
  • Springen Sie und führen Sie einen bösartigen Code aus

Die Hauptursache für einen Pufferüberlauf liegt darin, dass die Benutzereingaben im Programm nicht sorgfältig geprüft werden.

I/O-Multiplexing

IO-Multiplexing bedeutet, dass der Kernel den Prozess benachrichtigt, sobald er feststellt, dass eine oder mehrere von einem Prozess angegebene IO-Bedingungen zum Lesen bereit sind. IO-Multiplexing ist für die folgenden Fälle anwendbar :

  • E/A-Multiplexing muss verwendet werden, wenn Clients mit mehreren Deskriptoren arbeiten (normalerweise interaktive Eingabe- und Netzwerk-Sockets).
  • Es ist zwar möglich, aber selten, dass ein Client mehrere Sockets gleichzeitig verarbeiten kann.
  • Wenn ein TCP-Server sowohl Listening-Sockets als auch verbundene Sockets verarbeitet, wird im Allgemeinen I/O-Multiplexing verwendet.
  • Wenn ein Server sowohl TCP als auch UDP verarbeiten muss, wird im Allgemeinen E/A-Multiplexing verwendet.
  • Wenn ein Server mehrere Dienste oder mehrere Protokolle abwickelt, wird im Allgemeinen I/O-Multiplexing verwendet.
  • Im Vergleich zur Multiprozess- und Multithread-Technologie besteht der größte Vorteil der E/A-Multiplexing-Technologie darin, dass der Systemaufwand gering ist und das System keine Prozesse/Threads erstellen und diese Prozesse/Threads nicht verwalten muss. Dadurch wird der Systemaufwand erheblich reduziert.

Abschließend möchte ich Ihnen ein Github-Warehouse mit mehr als 300 von Dabin zusammengestellten klassischen Computerbuch-PDFs vorstellen, darunter C-Sprache, C++, Java, Python, Front-End, Datenbank, Betriebssystem, Computernetzwerk und Datenstruktur und Algorithmen, maschinelles Lernen, Programmierleben usw., Sie können es starten. Wenn Sie das nächste Mal nach einem Buch suchen, suchen Sie direkt danach, das Lager wird kontinuierlich aktualisiert ~

Github-Adresse

おすすめ

転載: blog.csdn.net/Tyson0314/article/details/131543877