table of contents
SYSCALL(2) | Manuel du programmeur Linux | SYSCALL(2) |
NOM¶
syscall - appel système indirect
SYNOPSIS¶
#define _GNU_SOURCE /* Consultez feature_test_macros(7) */ #include <unistd.h> #include <sys/syscall.h> /* Pour les définitions de SYS_xxx */
long syscall(long numéro, ...);
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) en cas d'erreur.
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 en mode petit boutiste :
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 pwritev2(2). Bienvenue dans le monde fantastique de l'héritage 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 utilisé pour indiquer le numéro de l'appel système, le registre utilisé comme code de retour de l'appel système et le registre utilisé pour signaler une erreur.
arch/ABI | instruction | syscall # | retval | erreur | Notes |
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] |
nios2 | trap | r2 | r2 | r7 | |
parisc | 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 | - |
Notes :
- [1]
- Sur quelques architectures, un registre est utilisé comme un booléen (0 indiquant aucune erreur et -1 indiquant une erreur) pour signaler que l'appel système a échoué. La valeur de l'erreur est toujours contenue dans le registre renvoyé. Sur sparc, le carry bit (csr) dans le registre d'état du processeur (psr) est utilisé à la place d'un registre entier.
- [2]
- NR est le numéro de l'appel système.
- [3]
- 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.
- [4]
- Sur SuperH, le numéro de capture contrôle le nombre maximal d'arguments passés. Un trapà 0 argument, un trapzéro ou un argument, et ainsi de suite jusqu'à trapsystème à sept arguments.
- [5]
- L'ABI x32 utilise la même instruction que l'ABI x86-64 et est utilisée sur les même processeurs. Pour les différencier, le masque de bit __X32_SYSCALL_BIT est associé par un OU binaire dans le numéro d'appel système pour les appels système de l'ABI x32. Les deux tables d'appels système sont néanmoins disponibles, aussi, définir le bit n'est pas une nécessité absolue.
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 | 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 | - | |
nios2 | r4 | r5 | r6 | r7 | r8 | r9 | - | |
parisc | 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 | - |
Notes :
- [1]
- 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.
EXEMPLE¶
#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); }
VOIR AUSSI¶
COLOPHON¶
Cette page fait partie de la publication 4.16 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.
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 à debian-l10n-french@lists.debian.org.
30 avril 2018 | Linux |