table of contents
SYSCALL(2) | Linux-Programmierhandbuch | SYSCALL(2) |
BEZEICHNUNG¶
syscall - indirekter Systemaufruf
ÜBERSICHT¶
#define _GNU_SOURCE /* siehe feature_test_macros(7) */ #include <unistd.h> #include <sys/syscall.h> /* Für SYS_xxx-Definitionen */
long syscall(long Nummer, …);
BESCHREIBUNG¶
syscall() ist eine kleine Bibliotheksfunktion, die den Systemaufruf auslöst, dessen Assemblersprachen-Schnittstelle in Nummer mit den festgelegten Argumenten angegeben wurde. Der Einsatz von syscall() ist beispielsweise hilfreich, wenn ein Systemaufruf ausgelöst werden soll, der in der C-Bibliothek keine Wrapper-Funktion hat.
syscall() speichert CPU-Register vor der Durchführung des Systemaufrufs, stellt die Register nach der Rückkehr von dem Systemaufruf wieder her und speichert alle vom Systemaufruf zurückgelieferten Fehler-Codes in errno(3), falls ein Fehler auftritt.
Die symbolischen Konstanten für die Systemaufrufnummern können in der Header-Datei <sys/syscall.h> gefunden werden.
RÜCKGABEWERT¶
Der Rückgabewert wird durch den ausgelösten Systemaufruf definiert. Im Allgemeinen zeigt ein Rückgabewert 0 einen Erfolg an. Ein Rückgabewert -1 zeigt einen Fehler und ein Fehler-Code wird in errno gespeichert.
ANMERKUNGEN¶
syscall() erschien erstmalig in 4BSD.
Architekturspezifische Anforderungen¶
Jede Architektur-ABI hat ihre eigenen Anforderungen, wie Argumente für Systemaufrufe an den Kernel übergeben werden. Für Systemaufrufe mit Glibc-Wrapper (beispielsweise die meisten Systemaufrufe) handhabt Glibc die Details des Kopierens der Argumente in die richtigen Register auf eine Weise, die für die Architektur angemessen ist. Wird allerdings syscall() zum Durchführen eines Systemaufrufs verwandt, könnte der Aufrufende die architekturabhängigen Details selber handhaben müssen. Diese Anforderung wird auf bestimmten 32-bit-Architekturen am häufigsten angetroffen.
Auf dem ABI der eingebetteten ARM-Architektur (EABI) muss beispielsweise ein 64-bit-Wert (z.B. long long) an ein gerades Registerpaar ausgerichtet werden. Wird daher syscall() anstelle des von Glibc bereitgestellten Wrappers verwandt, müsste der Systemaufruf readahead() in der folgenden Weise auf der ARM-Architektur mit dem ABI im Modus »little endian« ausgelöst werden:
syscall(SYS_readahead, fd, 0,
(unsigned int) (offset & 0xFFFFFFFF),
(unsigned int) (offset >> 32),
count);
Da das Argument »offset« 64 bit beträgt und das erste Argument (fd) an r0 übergeben wird, muss der aufrufende den 64-bit-Wert manuell zerteilen und ausrichten, so dass er an das Register-Paar r2/r3 übergeben wird. Das bedeutet, dass ein Blindwert in r1 (dem zweiten Argument von 0) eingefügt werden muss. Es muss auch darauf geachtet werden, dass die Zerteilung den Endian-Konventionen folgt (gemäß der C-ABI dieser Plattform).
Ähnliche Probleme können auf MIPS mit dem O32-ABI, auf PowerPC mit dem 32-bit-ABI und auf Xtensa auftreten.
Beachten Sie, dass das Parisc-C-ABI zwar auch ausgerichtete Registerpaare verwendet, aber eine Ausgleichs-Schicht verwendet, um das Problem vor dem Anwendungsraum zu verstecken.
Die betroffenen Systemaufrufe sind fadvise64_64(2), ftruncate64(2), posix_fadvise(2), pread64(2), pwrite64(2), readahead(2), sync_file_range(2) und truncate64(2).
Dies betrifft Systemaufrufe, die manuell 64-bit-Werte auseinandernehmen und zusammensetzen, wie _llseek(2), preadv(2), preadv2(2), pwritev(2) und pwritev2(2), nicht. Willkomen in der wundervollen Welt der historischen Altlasten.
Architekturabhängige Aufrufkonventionen¶
Jede Architektur hat ihre eigene Art, den Kernel aufzurufen und Argumente zu übergeben. Die Details für die verschiedenen Architekturen sind in zwei nachfolgenden Tabellen dargestellt.
Die erste Tabelle führt die Anweisungen auf, die zum Übergang in den Kernelmodus verwandt werden (dies könnte nicht die schnellste oder beste Art zum Übergang in den Kernel sein, bitte schauen Sie auch in vdso(7)), das Register, das zur Angabe der Systemaufrufnummer, das Register, das zur Rückgabe des Ergebnisses des Systemaufrufs und das Register, das zur Signalisierung eines Fehlers verwandt wird.
Arch/ABI | Anweisung | syscall No. | Rückwert | Fehler | Hinweise |
alpha | callsys | v0 | a0 | a3 | [1] |
Arc | trap0 | r8 | r0 | - | |
Arm/OABI | swi NR | - | a1 | - | [2] |
Arm/EABI | swi 0x0 | r7 | r0 | - | |
Arm64 | svc #0 | x8 | x0 | - | |
Blackfin | excpt 0x0 | P0 | R0 | - | |
I386 | int $0x80 | eax | eax | - | |
Ia64 | break 0x100000 | r15 | r8 | r10 | [1] |
M68k | trap #0 | d0 | d0 | - | |
Microblaze | brki r14,8 | r12 | r3 | - | |
Mips | syscall | v0 | v0 | a3 | [1] |
Nios II | trap | r2 | r2 | r7 | |
PA-RISC | ble 0x100(%sr2, %r0) | r20 | r28 | - | |
PowerPC | sc | r0 | r3 | r0 | [1] |
riscv | scall | a7 | a0 | - | |
S390 | svc 0 | r1 | r2 | - | [3] |
S390x | svc 0 | r1 | r2 | - | [3] |
SuperH | trap #0x17 | r3 | r0 | - | [4] |
SPARC/32 | t 0x10 | g1 | o0 | psr/csr | [1] |
SPARC/64 | t 0x6d | g1 | o0 | psr/csr | [1] |
Tile | swint1 | R10 | R00 | R01 | [1] |
X86-64 | syscall | rax | rax | - | [5] |
X32 | syscall | rax | rax | - | [5] |
Xtensa | syscall | a2 | a2 | - |
Hinweise:
- [1]
- Auf einigen Architekturen wird ein Register als logischer Wert verwandt (0 zeigt an, dass kein Fehler vorliegt und -1 zeigt Fehler an), um mitzuteilen, dass der Systemaufruf fehlschlug. Der tatsächliche Fehlerwert ist weiterhin in dem Rückliefer-Register enthalten. Auf Sparc wird das Zweierübergangsbit (csr) im Prozessorstatusregister (psr) anstelle eines vollständigen Registers verwandt.
- [2]
- NR ist die Nummer des Systemaufrufs.
- [3]
- Für S390 und S390x kann NR (die Nummer des Systemaufrufs) direkt mit svc NR übergeben werden, falls sie kleiner als 256 ist.
- [4]
- Auf SuperH steuert die Nummer der Ausnahmebehandlung die maximale Anzahl an übergebenen Argumenten. Ein trap #0x10 kann nur mit Systemaufrufen ohne Argument, ein trap #0x11 kann mit Systemaufrufen mit keinem oder einem Argument und so weiter verwandt werden, bis zu trap #0x17 für Systemaufrufe mit 7 Argumenten.
- [5]
- Das x32-ABI verwendet die gleichen Anweisungen wie das x86-64-ABI und wird auf den gleichen Prozessoren verwandt. Um sie zu unterscheiden, wird die Bitmaske __X32_SYSCALL_BIT mit einem bitweisen ODER mit der Systemaufrufnummer für Systemaufrufe unter dem x32-ABI verknüpft. Es sind allerdings beide Systemaufruftabellen verfügbar, so dass das Setzen des Bits keine harte Anforderung ist.
Die zweite Tabelle zeigt die Register, die zur Übergabe der Systemaufrufargumente verwandt werden.
Arch/ABI | Arg1 | Arg2 | Arg3 | Arg4 | Arg5 | Arg6 | Arg7 | Hinweise |
alpha | a0 | a1 | a2 | a3 | a4 | a5 | - | |
Arc | r0 | r1 | r2 | r3 | r4 | r5 | - | |
Arm/OABI | a1 | a2 | a3 | a4 | v1 | v2 | v3 | |
Arm/EABI | r0 | r1 | r2 | r3 | r4 | r5 | r6 | |
Arm64 | x0 | x1 | x2 | x3 | x4 | x5 | - | |
Blackfin | R0 | R1 | R2 | R3 | R4 | R5 | - | |
I386 | ebx | ecx | edx | esi | edi | ebp | - | |
Ia64 | out0 | out1 | out2 | out3 | out4 | out5 | - | |
M68k | d1 | d2 | d3 | d4 | d5 | a0 | - | |
Microblaze | r5 | r6 | r7 | r8 | r9 | r10 | - | |
MIPS/o32 | a0 | a1 | a2 | a3 | - | - | - | [1] |
MIPS/n32,64 | a0 | a1 | a2 | a3 | a4 | a5 | - | |
Nios II | r4 | r5 | r6 | r7 | r8 | r9 | - | |
PA-RISC | r26 | r25 | r24 | r23 | r22 | r21 | - | |
PowerPC | r3 | r4 | r5 | r6 | r7 | r8 | r9 | |
riscv | a0 | a1 | a2 | a3 | a4 | a5 | - | |
S390 | r2 | r3 | r4 | r5 | r6 | r7 | - | |
S390x | r2 | r3 | r4 | r5 | r6 | r7 | - | |
SuperH | r4 | r5 | r6 | r7 | r0 | r1 | r2 | |
SPARC/32 | o0 | o1 | o2 | o3 | o4 | o5 | - | |
SPARC/64 | o0 | o1 | o2 | o3 | o4 | o5 | - | |
Tile | R00 | R01 | R02 | R03 | R04 | R05 | - | |
X86-64 | rdi | rsi | rdx | r10 | r8 | r9 | - | |
X32 | rdi | rsi | rdx | r10 | r8 | r9 | - | |
Xtensa | a6 | a3 | a4 | a5 | a8 | a9 | - |
Hinweise:
- [1]
- Die Systemaufrufkonvention von MIPS/o32 übergibt die Argumente 5 bis 8 über den Benutzer-Stack.
Beachten Sie, dass diese Tabellen nicht die gesamte Aufrufkonvention abdecken–einige Architekturen könnten rücksichtslos andere, hier nicht aufgeführte Register belegen.
BEISPIEL¶
#define _GNU_SOURCE #include <unistd.h> #include <sys/syscall.h> #include <sys/types.h> #include <signal.h> int main(int argc, char *argv[]) {
pid_t tid;
tid = syscall(SYS_gettid);
syscall(SYS_tgkill, getpid(), tid, SIGHUP); }
SIEHE AUCH¶
KOLOPHON¶
Diese Seite ist Teil der Veröffentlichung 4.16 des Projekts Linux-man-pages. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können, sowie die aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.
ÜBERSETZUNG¶
Die deutsche Übersetzung dieser Handbuchseite wurde von Helge Kreutzmann <debian@helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer.
30. April 2018 | Linux |