Ich möchte den Begriff "Systemaufruf" verstehen. Ich weiß, dass Systemaufrufe verwendet werden, um Kernel-Services von einer Userspace-Anwendung abzurufen.
Der Teil, den ich klären muss, ist der Unterschied zwischen einem "Systemaufruf" und einer "C-Implementierung des Systemaufrufs".
Hier ist ein Zitat, das mich verwirrt:
Auf Unix-ähnlichen Systemen ist diese API in der Regel Teil einer Implementierung der C-Bibliothek (libc) wie glibc, die Wrapper-Funktionen für die Systemaufrufe bereitstellt, die häufig denselben Namen haben wie die von ihnen aufgerufenen Systemaufrufe
Was sind die "Systemaufrufe, die sie aufrufen"? Wo ist ihre Quelle? Kann ich sie direkt in meinen Code einfügen?
Ist der "Systemaufruf" im Allgemeinen nur eine POSIX-definierte Schnittstelle, aber um die Implementierung tatsächlich zu sehen, könnte man die C-Quelle untersuchen und darin sehen, wie der tatsächliche Benutzerbereich zur Kernel-Kommunikation tatsächlich verläuft?
Hintergrundinformation: Ich versuche zu verstehen, ob am Ende jede c-Funktion mit Geräten von interagiert /dev
.
quelle
getpid
Systemaufrufs im Linux-Kernel: lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337 . Und dies ist die Wrapper-Funktion in der GNU C-Standardbibliothek glibc-2.19: fossies.org/dox/glibc-2.19/… .Ein Systemaufruf ist eine Möglichkeit, Ihr Betriebssystem (Kernel) aufzufordern, bestimmte Vorgänge für Ihr Programm auszuführen, die das Programm selbst nicht ausführen kann (oder die einfach unpraktisch sind). Der Grund dafür, dass einige Operationen nicht ausgeführt werden können, besteht normalerweise darin, dass die Integrität des Systems beeinträchtigt werden kann, wenn ein zufälliges Programm sie ausführt, z.
POSIX definiert eine Schnittstelle für Programme, bestimmte Funktionen, die Ihr Programm aufrufen kann. Einige davon werden mehr oder weniger direkt in Systemaufrufe übersetzt, andere erfordern eine genauere Bearbeitung. Es ist die Laufzeit für Ihre Sprache, z. B. die C-Bibliothek, die für die Bereitstellung der POSIX-Schnittstelle verantwortlich ist und die Argumente paketiert und die Ergebnisse an den Aufrufer zurückgibt.
Unixy-Systeme bieten POSIX-Schnittstellen mehr oder weniger direkt als Systemaufrufe an. Normalerweise gibt es eine Möglichkeit, Systemaufrufe direkt aufzurufen.
syscall(2)
Informieren Sie sich über die Verwendung dieser Funktion unter Linux.quelle
strlen
,strcpy
,sqrt
undqsort
) kann und wahrscheinlich ist im User - Space, aus einer Bibliothek geladen. (Meistens libc; mathematische Funktionen wiesqrt
und die trigonometrischen und hyperbolischen Funktionen befinden sich wahrscheinlich in libm, der mathematischen Bibliothek.)… (Fortsetzung)fork
,kill
oderopen
Funktion, da diese den Zugang benötigen , um den Betriebssystemkern Speicherplatz ( zum Beispiel der Prozesstabelle) oder privilegierte Befehle (zB I / O). Daher muss sich der Code, der diese Funktionen ausführt, im Betriebssystemkern befinden. daher Systemfunktionen oder Systemaufrufe.Sicher, lass uns die vielen Richtungen machen, aus denen wir diesen Elefanten betrachten können. Sache.
Der eigentliche Systemaufruf ist in Ihrem erstellten Programm der Maschinenbefehl, der die Privilegieneskalation in den Kernelmodus auslöst, und im Kernel selbst ist es der Code, den der Befehl aufruft. Der libc-Code (und jede Sprachlaufzeit) richtet die Maschinenregister und speicherinternen Parameter ein, von denen der Kernel-Code erwartet, dass sie gefunden werden. Dies kann aufgrund von Einschränkungen bei dieser Maschinenanweisung zu merkwürdigen Fehlern führen.
Einmal im OS-Code selbst, gibt es ein bisschen Spiegelung der maschinenspezifischen Dinge, die die Userland-Laufzeit erledigt hat, und dann einen ganz normalen Unterprogrammaufruf.
Wenn Sie genau sehen möchten, wie dies in einem vollständigen Betriebssystem funktioniert, ziehen Sie die Kernelquelle (
git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
) und führen Sie zgit grep -i system\ call
. Ziehen Sie die Glibc-Quelle und tun Sie es ebenfalls.quelle
Zumindest unter Linux funktioniert der Systemaufrufmechanismus unter den meisten Architekturen, indem einige speziell formatierte Daten (normalerweise eine Art Struktur) entweder in einigen Registern oder in vordefinierten Speicheradressen abgelegt werden.
Das Problem besteht jedoch darin, dass die CPU gezwungen wird, in den Kernel-Speicher zu wechseln, damit sie den privilegierten Kernel-Code ausführen kann, um den Aufruf zu bearbeiten. Dies geschieht, indem ein Fehler erzwungen wird (ein Fehler ist eine Division durch 0, ein undefinierter Überlauf oder ein Segfault usw.), wodurch der Kernel gezwungen wird, die Ausführung zu übernehmen, um den Fehler zu behandeln.
Normalerweise behandelt der Kernel Fehler, indem er entweder den verursachenden Prozess beendet oder einen vom Benutzer bereitgestellten Handler ausführt. Im Fall eines Systemaufrufs werden stattdessen die vordefinierten Register und Speicherorte überprüft, und wenn sie eine Systemaufrufanforderung enthalten, wird diese unter Verwendung der vom Benutzerprozess in der In-Memory-Struktur bereitgestellten Daten ausgeführt. Dies muss normalerweise mit einer speziell von Hand gefertigten Baugruppe durchgeführt werden. Um dem Benutzer die Verwendung des Systemaufrufs zu erleichtern, muss die C-Bibliothek des Systems diesen als Funktion verpacken. Unter http://man7.org/linux/man-pages/man2/syscall.2.html finden Sie Informationen zur Funktionsweise von syscalls und wie Sie sie dann ohne C-Wrapper aufrufen können.
Dies wird zu stark vereinfacht. Dies gilt nicht für alle Architekturen (mips verfügt über eine spezielle Syscall-Anweisung) und funktioniert nicht unbedingt auf allen Betriebssystemen gleich. Wenn Sie dennoch Kommentare oder Fragen haben, wenden Sie sich bitte an.
Geändert: Beachten Sie, dass es sich bei Ihrem Kommentar zu Dingen in / dev / tatsächlich um eine übergeordnete Schnittstelle zum Kernel handelt, nicht um eine niedrigere. Diese Geräte verwenden tatsächlich (ungefähr) 4 Systemaufrufe darunter. Das Schreiben in sie ist dasselbe wie ein Write-Systemaufruf, das Lesen eines Read-Systemaufrufs, das Öffnen / Schließen derselben wie beim Open- und Close-Systemaufruf und das Ausführen eines Ioctl-Befehls bewirkt einen speziellen Ioctl-Systemaufruf, der an sich eine Schnittstelle für den Zugriff auf eines der vielen Ioctl-Befehle des Systems darstellt Anrufe (spezielle, normalerweise gerätespezifische Anrufe mit zu enger Verwendung, um einen vollständigen Systemaufruf für sie zu schreiben).
quelle
Jedem Systemaufruf ist eine Ganzzahl zugeordnet. Diese Ganzzahl ist eine Funktion des Rückgabewerts des Systemaufrufs, der Anzahl der Argumente für den Systemaufruf und des Typs der Argumente. Diese Systemaufrufnummer ist nichts anderes als ein Offset zum globalen Systemaufrufvektor. Dieser Vektor, auf den nur im privilegierten Modus zugegriffen werden kann, enthält einen Zeiger auf geeignete Handler. Beim Aufrufen eines Systemaufrufs würde ein Software-Interrupt (Trap-Interrupt) generiert, daher würde ein Trap-Handler ausgeführt, der festlegt, welcher Systemaufruf aufgerufen werden soll. Dann würde der Kernel die Argumente des vom Benutzer, der sich auf dem Stapel befindet, übergebenen Systemaufrufs in die Prozessorregister kopieren, und nach Beendigung des angeforderten Dienstes würden die Daten von den Prozessorregistern zurück in den Stapel kopiert. Dies ist einer der Gründe, warum es für Systemaufrufe nur wenige Argumente gibt.
quelle