syscall(2)

BEZEICHNUNG
syscall - indirekter Systemaufruf

BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)

ÜBERSICHT
#include <sys/syscall.h>      /* Definition der SYS_*-Konstanten */
#include <unistd.h>

long syscall(long Nummer, …);

    Mit Glibc erforderliche Feature-Test-Makros (siehe feature_test_macros(7)):

syscall():
    Seit Glibc 2.19:
        _DEFAULT_SOURCE
    Vor Glibc 2.19:
        _BSD_SOURCE || _SVID_SOURCE

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 in errno(3).

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 eine Fehlernummer wird in errno gespeichert.

FEHLER

ENOSYS
    Die angefragte Systemaufrufnummer ist nicht implementiert.

Andere Fehler hängen vom konkret aufgerufenen Systemaufruf ab.

GESCHICHTE
syscall() erschien erstmalig in 4BSD.

ANMERKUNGEN

  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(2) 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 und Parisc 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 oder die Register, die zur Rückgabe des Ergebnisses des Systemaufrufs und das Register, das zur Signalisierung eines Fehlers verwandt wird.
Arch/ABI | Anweisung | System | Rück | Rück | Fehler | Hinweise
 |  | Aufruf # | Wert | Wert2
alpha | callsys | v0 | v0 | a4 | a3 | 1, 6
Arc | trap0 | r8 | r0 | - | -
Arm/OABI | swi NR | - | r0 | - | - | 2
Arm/EABI | swi 0x0 | r7 | r0 | r1 | -
Arm64 | svc #0 | w8 | x0 | x1 | -
Blackfin | excpt 0x0 | P0 | R0 | - | -
I386 | int $0x80 | eax | eax | edx | -
Ia64 | break 0x100000 | r15 | r8 | r9 | r10 | 1, 6
Loongarch | syscall 0 | a7 | a0 | - | -
M68k | trap #0 | d0 | d0 | - | -
Microblaze | brki r14,8 | r12 | r3 | - | -
Mips | syscall | v0 | v0 | v1 | a3 | 1, 6
Nios II | trap | r2 | r2 | - | r7
PA-RISC | ble 0x100(%sr2, %r0) | r20 | r28 | - | -
PowerPC | sc | r0 | r3 | - | r0 | 1
PowerPC64 | sc | r0 | r3 | - | cr0.SO | 1
riscv | ecall | a7 | a0 | a1 | -
S390 | svc 0 | r1 | r2 | r3 | - | 3
S390x | svc 0 | r1 | r2 | r3 | - | 3
SuperH | trapa #31 | r3 | r0 | r1 | - | 4, 6
SPARC/32 | t 0x10 | g1 | o0 | o1 | psr/csr | 1, 6
SPARC/64 | t 0x6d | g1 | o0 | o1 | psr/csr | 1, 6
Tile | swint1 | R10 | R00 | - | R01 | 1
X86-64 | syscall | eax | rax | rdx | - | 5
X32 | syscall | eax | rax | rdx | - | 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. Auf PowerPC64 wird das zusammenfassende Überlaufbit (SO) im Feld 0 des Bedingungsregisters (cr0) 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 werden aus historischen Gründen zusätzliche Nummern für Ausnahmebehandlungen unterstützt, aber trapa#31 ist die empfohlene »vereinigte« ABI.

[5] Das x32-ABI nutzt die Systemaufruf-Tabelle der x86-64-ABI mit, es gibt aber kleine Nuancen:

    •   Um anzuzeigen, dass ein Systemaufruf unter der x32-ABI erfolgt, wird ein zusätzliches Bit (__X32_SYSCALL_BIT) durch ein bitweises ODER mit der Systemaufrufnummer verknüpft. Das von einem Prozess verwandte ABI betrifft einige Prozessverhalten, einschließlich der Signalverarbeitung oder dem Neustarten von Systemaufrufen.

    •   Da x32 andere Größen für long und Zeigertypen hat, ist das Layout einiger Strukturen (aber nicht aller: struct timeval oder struct rlimit sind beispielsweise 64 bit) anders. Um damit umzugehen, werden zusätzliche Systemaufrufe zu der Systemaufruftabelle hinzugefügt, beginnend bei Nummer 512 (ohne das __X32_SYSCALL_BIT). Beispielsweise ist __NR_readv als 19 für das x86-64-ABI und als __X32_SYSCALL_BIT | 515 für das x32-ABI definiert. Die meisten dieser zusätzlichen Systemaufrufe sind tatsächlich zu den Systemaufrufen, die zur Bereitstellung der i386-Kompatibilität verwandt werden, identisch. Es gibt allerdings ein paar bemerkenswerte Ausnahmen, wie preadv2(2), das Einheiten struct iovec mit 4-byte-Zeigern und Größen (»compat_iovec« in der Kernelsprache) verwendet, aber ein 8-byte Argument pos in einem einzelnen Register (und nicht in zweien) übergibt, wie dies in jedem anderen ABI erfolgt.

[6] Einige Architekturen (konkret Alpha, IA-64, MIPS, SuperH, Sparc/32 und Sparc/64) verwenden ein zweites Register (»Rückwert2« in der obigen Tabelle), um einen zweiten Rückgabewert von dem Systemaufruf pipe(2) zurückzugeben. Alpha verwendet diese Technik auch in den architekturspezifischen Systemaufrufen getxpid(2), getxuid(2) und getxgid(2). Andere Architekturen verwenden das zweite Rückgaberegister in der Systemaufrufschnittstelle nicht, selbst wenn es in der System-V-ABI definiert 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 | r0 | r1 | r2 | r3 | r4 | r5 | r6
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 | -
Loongarch | a0 | a1 | a2 | a3 | a4 | a5 | a6
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
PowerPC64 | r3 | r4 | r5 | r6 | r7 | r8 | -
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.

BEISPIELE
    #define _GNU_SOURCE
    #include <signal.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <unistd.h>

    int
    main(void)
    {
        pid_t tid;

        tid = syscall(SYS_gettid);
        syscall(SYS_tgkill, getpid(), tid, SIGHUP);
    }

SIEHE AUCH
_syscall(2), intro(2), syscalls(2), errno(3), vdso(7)

Ü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 (https://www.gnu.org/licenses/gpl-3.0.html) 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 (debian-l10n-german@lists.debian.org).