Was ist ein Linux-Systemaufruf?

What Is Linux System Call



Bevor wir uns mit der Definition eines Linux-Systemaufrufs und den Details seiner Ausführung befassen, ist es am besten, mit der Definition der verschiedenen Softwareschichten eines typischen Linux-Systems zu beginnen.

Der Linux-Kernel ist ein spezialisiertes Programm, das auf der niedrigsten verfügbaren Ebene auf Ihrer Hardware bootet und ausgeführt wird. Es hat die Aufgabe, alles zu orchestrieren, was auf dem Computer ausgeführt wird, einschließlich der Handhabung von Tastatur-, Festplatten- und Netzwerkereignissen, um Zeitscheiben für die parallele Ausführung mehrerer Programme bereitzustellen.







Wenn der Kernel ein Programm auf Benutzerebene ausführt, virtualisiert er den Speicherplatz, sodass Programme glauben, dass sie der einzige Prozess sind, der im Speicher läuft. Diese schützende Blase aus Hardware- und Softwareisolierung erhöht die Sicherheit und Zuverlässigkeit. Eine nicht privilegierte Anwendung kann nicht auf den Speicher anderer Programme zugreifen, und wenn dieses Programm abstürzt, wird der Kernel beendet, damit er dem Rest des Systems keinen Schaden zufügen kann.



Durchbrechen der Barriere mit Linux-Systemaufrufen

Diese Isolationsschicht zwischen nicht privilegierten Anwendungen bietet eine hervorragende Grenze zum Schutz anderer Anwendungen und Benutzer auf dem System. Ohne eine Möglichkeit, sich mit den anderen Elementen im Computer und der Außenwelt zu verbinden, könnten Programme jedoch nicht viel erreichen.



Um die Interaktion zu erleichtern, bezeichnet der Kernel ein Software-Gate, das es dem laufenden Programm ermöglicht, den Kernel anzufordern, in seinem Namen zu handeln. Diese Schnittstelle wird als Systemaufruf bezeichnet.





Da Linux der UNIX-Philosophie folgt, dass alles eine Datei ist, können viele Funktionen durch Öffnen und Lesen oder Schreiben in eine Datei ausgeführt werden, die ein Gerät sein könnte. Unter Windows können Sie beispielsweise eine Funktion namens CryptGenRandom verwenden, um auf zufällige Bytes zuzugreifen. Unter Linux kann dies jedoch durch einfaches Öffnen der Datei /dev/urandom und Lesen von Bytes daraus mithilfe von Standard-Datei-Ein-/Ausgabe-Systemaufrufen erfolgen. Dieser entscheidende Unterschied ermöglicht eine einfachere Systemaufrufschnittstelle.

Hauchdünne Hülle

In den meisten Anwendungen werden Systemaufrufe nicht direkt an den Kernel gesendet. Praktisch alle Programme verlinken in der Standard-C-Bibliothek, die einen dünnen, aber wichtigen Wrapper um Linux-Systemaufrufe bietet. Die Bibliothek stellt sicher, dass die Funktionsargumente in die richtigen Prozessorregister kopiert werden und gibt dann den entsprechenden Linux-Systemaufruf aus. Wenn Daten vom Aufruf empfangen werden, interpretiert der Wrapper die Ergebnisse und gibt sie auf konsistente Weise an das Programm zurück.



Hinter den Kulissen

Jede Funktion in einem Programm, die mit dem System interagiert, wird schließlich in einen Systemaufruf übersetzt. Um dies in Aktion zu sehen, beginnen wir mit einem einfachen Beispiel.

Leerehauptsächlich() {
}

Dies ist wahrscheinlich das trivialste C-Programm, das Sie jemals sehen werden. Es übernimmt einfach die Kontrolle über den Haupteinstiegspunkt und verlässt ihn dann. Es gibt nicht einmal einen Wert zurück, da main als void definiert ist. Speichern Sie die Datei als ctest.c und kompilieren wir sie:

gcc ctest.C -der ctest

Sobald es kompiliert ist, können wir die Dateigröße mit 8664 Bytes sehen. Es kann auf Ihrem System leicht variieren, sollte aber etwa 8k betragen. Das ist eine Menge Code, nur um ein- und auszusteigen! Der Grund für 8k ist, dass die libc-Laufzeit enthalten ist. Selbst wenn wir die Symbole entfernen, sind es immer noch etwas über 6k.

In einem noch einfacheren Beispiel können wir den Linux-Systemaufruf beenden, anstatt uns von der C-Laufzeit abhängig zu machen.

Leere_Anfang() {
asm('movl $1,%eax;'
'xorl %ebx,%ebx;'
'int $0x80');
}

Hier verschieben wir 1 in das EAX-Register, löschen das EBX-Register (das sonst den Rückgabewert enthalten würde) und rufen dann den Linux-Systemaufruf-Interrupt 0x80 (oder 128 dezimal) auf. Dieser Interrupt veranlasst den Kernel, unseren Aufruf zu verarbeiten.

Wenn wir unser neues Beispiel namens asmtest.c kompilieren und die Symbole entfernen und die Standardbibliothek ausschließen:

gcc-S-nostdlib asmtest.C -o asmtest

Wir produzieren eine Binärdatei von weniger als 1k (auf meinem System ergibt es 984 Byte). Der größte Teil dieses Codes besteht aus ausführbaren Headern. Wir rufen jetzt den direkten Linux-Systemaufruf auf.

Für alle praktischen Zwecke

In fast allen Fällen müssen Sie in Ihren C-Programmen keine direkten Systemaufrufe durchführen. Wenn Sie jedoch Assembler verwenden, kann dies erforderlich sein. Bei der Optimierung wäre es jedoch am besten, die C-Bibliotheksfunktionen die Systemaufrufe durchführen zu lassen und nur Ihren leistungskritischen Code in die Assemblydirektiven einzubetten.

So programmieren Sie Systemaufruf-Tutorials

Liste aller Systemaufrufe

Wenn Sie eine Liste aller verfügbaren Systemaufrufe für Linux sehen möchten, können Sie diese Referenzseiten überprüfen: Vollständige Liste der Systemaufrufe auf LinuxHint.com, filippo.io/linux-syscall-table/ und oder syscalls.kernelgrok.com