Experimentelle Analyse: https://www.zhihu.com/column/c_142990858
Linux ist ein Open -Source -Betriebssystem. Benutzer können den Kernel nach ihrem eigenen System anpassen und ändern, um Systeme mit angemesseneren Funktionen und höherer Betriebseffizienz anzupassen. Daher ist das Zusammenstellen des Linux -Kernels eine notwendige grundlegende Fähigkeit für die Kernelentwicklung.
Das Hinzufügen neuer Systemaufrufe nach Bedarf im System ist eine gemeinsame Methode, um den Kernel zu ändern. Durch dieses Experiment sollten die Leser den Prozess von Linux -Systemverarbeitungssystemaufrufen und die Methode zum Hinzufügen von Systemaufrufen verstehen.
(1) Fügen Sie einen Systemaufruf hinzu, um die Änderungs- oder Lesefunktion des netten Wertes des angegebenen Prozesses zu implementieren, und geben Sie den neuesten netten Wert und den Prioritäts -Prio des Prozesses zurück. Es wird empfohlen, den Prototyp als:
int mysetnice (pid_t pid, int flag, int niceValue, void __user * prio, void __user * schön);
Parameter Bedeutung: PID: Prozess -ID.
Flagge: Wenn der Wert 0 ist, bedeutet es, den schönen Wert zu lesen; Wenn der Wert 1 ist, bedeutet dies, den schönen Wert zu ändern.
PRIO, schön: Der aktuelle Priorität und der gute Wert des Prozesses. Rückgabewert: Rückgabe 0 Wenn der Systemaufruf erfolgreich ist, und den Fehlercode Efault zurückgeben, wenn der Systemaufruf fehlschlägt.
(2) Schreiben Sie einen einfachen Anwendungstest in (1) hinzugefügt.
(3) Wenn die Kernelfunktion von Linux im Programm aufgerufen wird, muss der Quellcode der relevanten Funktion eingehend gelesen werden.
Der von Linux bereitgestellte Modulmechanismus kann Linux -Funktionen dynamisch erweitern, ohne den Kernel neu zu kompilieren, und wurde bei der Implementierung vieler Funktionen des Linux -Kernels häufig verwendet. In diesem Experiment lernen wir die grundlegenden Konzepte, Prinzipien und Implementierungstechniken von Modulen und verwenden dann das Kernel -Modul, um auf die grundlegenden Informationen des Prozesses zu programmieren und zuzugreifen, wodurch unser Verständnis von Prozesskonzepten und Mastering -Modulprogrammierungstechniken verengt wird.
(1) Entwerfen Sie ein Modul, für das die Programmnamen, PID -Nummern, der Prozessstatus und die Prozessprioritäten aller Kernel -Threads im System aufgeführt sind.
(2) Entwerfen Sie ein Modul mit Parametern, deren Parameter die PID -Anzahl eines Prozesses sind. Die Funktion dieses Moduls besteht darin, die familiären Informationen des Prozesses einschließlich des Programmnamens und der PID -Nummer des übergeordneten Prozesses, des Bruderprozesses und des Kinderprozesses aufzulisten.
(3) Lesen Sie bitte die Quellcode -Implementierung der relevanten Kernelfunktionen, die im Programm basierend auf Ihrer eigenen Situation verwendet werden.
(1) Mit der Befehlsschnittstelle von Linux vertraut sein.
(2) Durch die Programmieranwendung von verwandten Systemen fordert die Linux -Prozesskontrolle unser Verständnis von Prozesskonzepten weiter, klären die Verbindung und die Unterschiede zwischen Prozessen und Programmen und verstehen die spezifische Bedeutung der gleichzeitigen Ausführung von Prozessen.
(3) Durch die Verwendung des Kommunikationsmechanismus des Linux -Pipeline, des Kommunikationsmechanismus des Nachrichtenwarteschlangens und des gemeinsamen Mechanismus des gemeinsamen Gedächtnisses das Verständnis verschiedener Arten von Prozesskommunikationsmethoden vertiefen.
(4) das Verständnis des Semaphor -Synchronisationsmechanismus durch die Anwendung von POSIX -Semaphoren in Linux vertiefen. (5) Lesen und analysieren Sie die Implementierung der zugehörigen Systemanrufe auf der Grundlage Ihrer eigenen Situation weiter und analysieren Sie sie weiter.
(1) Mit gemeinsamen Linux -Befehlen vertraut: PWD, UserAdd, Passwd, WHO, PS, Pstree, Kill, Top, LS, CD, MKDIR, RMDIR, CP, RM, MV, CAT, MEHR, GREP usw.
(2) Implementieren Sie eine simulierte Shell:
Schreiben Sie drei verschiedene Programme cmd1.c, cmd2.c und cmd3.c. Die Funktionen jedes Programms werden angepasst und in ausführbare Dateien CMD1, CMD2 bzw. CMD3 zusammengestellt. Schreiben Sie dann ein Programm, um die Funktion des Shell -Programms zu simulieren. Es kann einen untergeordneten Prozess für den entsprechenden Befehl erstellen, der auf der vom Benutzer eingegebenen Zeichenfolge basiert (die den entsprechenden Befehlsnamen darstellt) und das entsprechende Programm ausführen lässt. Der übergeordnete Prozess wartet auf das Ende des Kinderprozesses und wartet dann auf den nächsten Befehl. Wenn der empfangene Befehl exit ist, endet der übergeordnete Prozess. Wenn der empfangene Befehl ein ungültiger Befehl ist, wird "Befehl nicht gefunden" angezeigt und Sie warten weiter.
(3) Implementieren Sie ein Pipeline -Kommunikationsprogramm:
Eine Pipeline wird durch den übergeordneten Prozess erstellt, und dann werden drei untergeordnete Prozesse erstellt, und diese drei untergeordneten Prozesse verwenden die Pipeline, um mit dem übergeordneten Prozess zu kommunizieren: Der untergeordnete Prozess sendet Informationen, und der übergeordnete Prozess und andere drei untergeordnete Prozesse empfangen die Informationen nach allen Senden von Nachrichten. Der spezifische Kommunikationsinhalt kann nach Belieben entsprechend Ihren eigenen Bedürfnissen ausgelegt werden. Es ist erforderlich, verschiedene Situationen im Blockierungslese- und Schreibprozess zu testen, die Standardgröße der Pipeline zu testen und den Semaphor -Mechanismus des POSIX -Semaphors zu verwenden, um einen gegenseitig ausschließenden Zugriff auf die Pipeline zwischen den Prozessen zu erwerben. Führen Sie das Programm aus, um die tatsächliche Anzahl von Bytes zu beobachten, die unter verschiedenen Umständen gelesen und geschrieben werden.
(4) Verwenden Sie den Kommunikationsmechanismus für den Linux -Meldungswarteschlangen, um die Kommunikation zwischen zwei Threads zu realisieren:
Schreiben Sie ein Programm, um zwei Threads zu erstellen: Absender -Thread und Empfangs -Thread, in dem der Absendungs -Thread den Funktionssender () ausführt, der eine Nachrichtenwarteschlange erstellt, und schleifen Sie dann auf, um darauf zu warten, dass der Benutzer eine Zeichenfolge über das Terminal eingibt, und sendet die Zeichenzeichenfolge an den Empfänger -Thread über die Nachrichtenwarteschlange, bis der Benutzer "Exit" beendet ". Schließlich sendet es eine Nachricht "Ende" an den Empfänger -Thread und wartet auf die Antwort des Empfängers. Nach der Antwortmeldung werden die empfangenen Antwortinformationen auf dem Terminalbildschirm angezeigt, die entsprechende Meldungswarteschlange gelöscht und das Ausführen des Programms beendet. Der Empfänger -Thread wird receme () ausgeführt, der Nachrichten vom Absender über die Meldungswarteschlange empfängt und die Nachricht auf dem Terminalbildschirm angezeigt wird, bis er eine Nachricht mit "Ende" empfängt. Zu diesem Zeitpunkt sendet es eine Antwortnachricht "over" an den Absender und beendet das Programm des Programms. Verwenden Sie namenlose Semaphoren, um die Synchronisation und den gegenseitigen Ausschluss zwischen zwei Threads zu erreichen.
(5) Verwenden Sie den gemeinsamen Mechanismus der gemeinsamen Speicherkommunikation von Linux, um die Kommunikation zwischen zwei Prozessen zu realisieren:
Schreiben Sie einen Programmabsender, der einen gemeinsam genutzten Speicher erstellt, und wartet dann darauf, dass der Benutzer eine Zeichenfolge über das Terminal eingibt, und sendet die Zeichenzeichenfolge über den freigegebenen Speicher an den Empfänger. Schließlich wartet es auf die Antwort des Empfängers. Nach Erhalt der Antwortmeldung werden die empfangenen Antwortinformationen auf dem Terminalbildschirm angezeigt, den freigegebenen Speicher gelöscht und das ausgeführte Programm beendet. Schreiben Sie ein Empfängerprogramm, das Nachrichten vom Absender über den gemeinsam genutzten Speicher empfängt, die Nachricht auf dem Terminalbildschirm angezeigt und dann eine Antwortnachricht "über" über den Absender über den freigegebenen Speicher sendet und das Programm des Programms beendet. Verwenden Sie ein benanntes Semaphor- oder System -V -Semaphor, um sich gegenseitig ausschließende und synchrone Verwendung des gemeinsam genutzten Speichers durch zwei Prozesse zu erreichen.
Durch die Verwaltung bestimmter Dateispeicherraum, die physische Struktur von Dateien, Verzeichnisstruktur und Dateivorgänge werden wir unser Verständnis der internen Datenstruktur, Funktionen und Implementierungsprozesse des Dateisystems vertiefen.
(1) Öffnen Sie einen virtuellen Festplattenraum im Speicher als Dateispeicherpartition und implementieren Sie ein einfaches Dateisystem in einem einzelnen Benutzer-Task-System basierend auf Multi-Level-Verzeichnissen. Beim Verlassen des Dateisystems sollte das virtuelle Dateisystem als Datei auf der Festplatte gespeichert werden, damit es das nächste Mal in den Speicherplatz Virtual Disk im Speicher wiederhergestellt werden kann.
(2) Die Zuweisung des Speicherplatzes für Datei kann durch explizite Verknüpfungszuweisung oder andere Methoden erfolgen.
(3) Sie können Bit -Diagramme oder andere Methoden auswählen, um den freien Speicherplatz zu verwalten. Wenn Bitmap zum Verwalten von Dateispeicherraum und zur Verwendung einer explizite Verknüpfungszuweisung verwendet wird, kann Bitmap in Fett zusammengeführt werden.
(4) Die Dateiverzeichnisstruktur verwendet eine mehrstufige Verzeichnisstruktur. Der Einfachheit halber können Indexknoten verwendet werden, jedes Verzeichniselement sollte Informationen wie Dateinamen, physische Adresse, Länge usw. enthalten, und die Lese- und Schreibdateien können auch über Verzeichniselemente geschützt werden.
(5) Die folgenden Operationsbefehle sind erforderlich: