syscall
Section: System Calls (2)
Updated: 5 février 2023
Index
Return to Main Contents
NOM
syscall - appel système indirect
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
SYNOPSIS
#include <sys/syscall.h> /* Définition des constantes SYS_* */
#include <unistd.h>
long syscall(long numéro, ...);
Exigences de macros de test de fonctionnalités pour la glibc (consulter
feature_test_macros(7)) :
syscall()
Depuis la glibc 2.19:
_DEFAULT_SOURCE
Avant la glibc 2.19:
_BSD_SOURCE || _SVID_SOURCE
DESCRIPTION
syscall() est une petite fonction de bibliothèque qui invoque l'appel
système dont l'interface en assembleur a le numéro indiqué avec les
arguments donnés. L'utilisation de syscall() est pratique, par exemple,
pour invoquer un appel système qui n'a pas de fonction d'enveloppe dans la
bibliothèque C.
syscall() sauve les registres du processeur avant de faire l'appel
système, restaure les registres au retour de l'appel système et stocke tous
les codes d'erreur renvoyés par l'appel système dans errno(3).
Les constantes symboliques correspondant aux appels système sont dans le
fichier d'en-tête <sys/syscall.h>.
VALEUR RENVOYÉE
La valeur de retour est définie par l'appel système invoqué. En général, une
valeur de retour 0 indique une réussite. Une valeur de retour de -1
indique une erreur, et un code d'erreur est fourni dans errno.
NOTES
syscall() est apparu dans BSD 4.
Exigences dépendantes de l'architecture
L'ABI de chaque architecture possède ses propres exigences sur la façon dont
les paramètres des appels système sont passés au noyau. Pour les appels
système qui ont une fonction d'enveloppe de la glibc (comme par exemple la
plupart des appels système), la glibc s'occupe des détails pour copier les
arguments dans les bons registres d'une manière adaptée à chaque
architecture. Cependant, en utilisant syscall() pour effectuer un appel
système, l'appelant peut avoir besoin de gérer certains détails dépendants
de l'architecture ; cette exigence est en particulier rencontrée sur
certaines architectures 32 bits.
Par exemple, pour l'Embedded ABI (EABI) de l'architecture ARM, une valeur
64 bits (c'est-à-dire un long long) doit être alignée sur une paire de
registres paire. Ainsi, en appelant syscall() au lieu de la fonction
d'enveloppe fournie par la glibc, l'appel système readahead() devrait
être effectué ainsi sur l'architecture ARM avec l'EABI :
syscall(SYS_readahead, fd, 0,
(unsigned int) (offset & 0xFFFFFFFF),
(unsigned int) (offset >> 32),
count);
Comme le paramètre offset est 64 bits, et le premier argument (fd) est
passé dans r0, l'appelant doit manuellement découper et aligner la valeur
64 bits afin de la passer dans la paire de registres r2/r3. Cela
implique de passer une valeur fantôme dans r1 (le second argument, qui
vaut 0). Il faut également veiller à ce que la division respecte les
conventions endian (selon l'ABI C de la plateforme).
Des problèmes similaires peuvent survenir sur MIPS avec l'ABI O32, sur
PowerPC avec l'ABI 32 bits, et sur Xtensa.
Notez qu'alors que l'ABI parisc C utilise aussi des paires de registres
alignés, il utilise une couche shim pour cacher le résultat de l'espace
utilisateur.
Les appels système concernés sont fadvise64_64(2), ftruncate64(2),
posix_fadvise(2), pread64(2), pwrite64(2), readahead(2),
sync_file_range(2) et truncate64(2).
Cela n'affecte pas les appels système qui séparent et assemblent
manuellement les valeurs 64 bits telles que _llseek(2), preadv(2),
preadv2(2), pwritev(2) et pwrite2(2). Bienvenue dans le monde
fanstastique du bagage historique.
Conventions d'appel par architecture
Chaque architecture possède sa façon propre d'invoquer et de passer des
paramètres au noyau. Les détails pour diverses architectures sont donnés
dans les deux tableaux ci-dessous.
Le premier tableau liste l'instruction utilisée pour passer en mode noyau
(qui n'est pas forcément la méthode la meilleure ou la plus rapide, vous
devriez consulter vdso(7)), le registre (ou les registres) utilisé(s)
pour indiquer le numéro de l'appel système, et le registre utilisé comme
code de retour de l'appel système, et le registre utilisé pour signaler une
erreur.
Arch/ABI | Instruction | Appel | Ret | Ret | Erreur | Notes
|
| | système n° | val | val2 | |
|
|
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
|
nios2 | trap | r2 | r2 | - | r7 |
|
parisc | 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 | rax | rax | rdx | - | 5
|
x32 | syscall | rax | rax | rdx | - | 5
|
xtensa | syscall | a2 | a2 | - | - |
|
Notes :
- •
-
Sur quelques architectures, un registre est utilisé comme un boléen (0
indiquant aucune erreur et -1 indiquant une erreur) pour signaler que
l'appel système a échoué. La valeur de l'erreur actuelle est toujours
contenue dans le registre renvoyé. Sur sparc, le bit de transport (carry
bit, csr) dans le registre d'état du processeur (psr) est utilisé au
lieu d'un registre entier. Sur powerpc64, le bit de débordement (overflow
bit) sommaire (SO) dans le champ 0 du registre de condition (cr0) est
utilisé.
- •
-
NR est le numéro de l'appel système.
- •
-
Pour s390 et s390x, NR (le numéro de l'appel système) peut être passé
directement avec svc NR s'il est inférieur à 256.
- •
-
Sur SuperH, des numéros de capture (« trap ») supplémentaires sont pris en
charge pour des raisons historiques mais trapa#31 est l'ABI « unifiée »
recommandée.
- •
-
Les ABI x32 partagent la table syscall avec l'ABI x86-64, mais avec quelques
nuances :
-
- •
-
De manière à indiquer qu'un appel système est appelé sous une ABI x32, un
bit additionnel, _X32_SYSCALL_BIT, est associé par un OU binaire avec
le numéro d'appel système. L'ABI utilise un processus qui influe sur le
comportement des processus, comme le traitement des signaux ou redémarrage
d'un appel système.
- •
-
Comme x32 a des tailles différentes pour long et les types « pointeur »,
les dispositions de quelques structures (mais pas toutes ; struct timeval
ou struct rlimit sont en 64 bits, par exemple) sont différentes. Pour
manipuler cela des appels système supplémentaires sont ajoutés à la table
d'appel système, commençant au numéro 512 (sans le _X32_SYSCALL BIT). Par
exemple, _NR_ready est défini à 19 pour l'ABI x86-64 et comme
_X32_SYSCALL_BIT | 515 pour l'ABI x32. La plupart de ces appels
système additionnels sont actuellement identiques aux appels système
utilisés pour fournir la compatibilité i386. Cependant, il y a quelques
exceptions notables, comme avec prreadv2(2), qui utilisent une entité
struct iovec avec des pointeurs et des tailles (« compat_iovec » au
niveau du noyau) en 4 bits, mais passe un argument pos 8 bits dans un
seul registre et non deux comme il est fait dans toute autre ABI.
- •
-
Quelques architectures (nommément : Alpha, IA-64, MIPS, SuperH, sparc/32 et
sparc/64) utilisent un registre additionnel (« Retval2 » dans la table
ci-dessus) pour renvoyer une deuxième valeur de renvoi de l'appel système
pipe(2) ; Alpha utilise aussi cette technique pour les appels système
getxgid(2), getxuid(2) et getxpid(2) spécifiques à
l'architecture. Les autres architectures n'utilisent pas le registre de la
seconde valeur renvoyée dans l'interface de l'appel système, même s'il est
défini dans l'ABI de System V.
Le second tableau montre les registres utilisés pour passer les paramètres
de l'appel système.
Arch/ABI | arg1 | arg2 | arg3 | arg4 | arg5 | arg6 | arg7 | Notes
|
|
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 | - |
|
nios2 | r4 | r5 | r6 | r7 | r8 | r9 | - |
|
parisc | 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 | - |
|
Notes :
- •
-
La convention d'appel système mips/o32 passe les arguments 5 à 8 sur la pile
utilisateur.
Notez que ces tableaux ne couvrent pas l'ensemble des conventions d'appel
système, certaines architectures peuvent écraser sans distinction d'autres
registres non listés ici.
EXEMPLES
#define _GNU_SOURCE
#include <signal.h>
#include <sys/syscall.h>
#include <unistd.h>
int
main(void)
{
pid_t tid;
tid = syscall(SYS_gettid);
syscall(SYS_tgkill, getpid(), tid, SIGHUP);
}
VOIR AUSSI
_syscall(2), intro(2), syscalls(2), errno(3), vdso(7)
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>
et
bubu <bubub@no-log.org>
Cette traduction est une documentation libre ; veuillez vous reporter à la
GNU General Public License version 3
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- VALEUR RENVOYÉE
-
- NOTES
-
- Exigences dépendantes de l'architecture
-
- Conventions d'appel par architecture
-
- EXEMPLES
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 20:34:44 GMT, May 22, 2024