write(2)

Appel système

Appel système qui transmet des octets à un descripteur de fichier (1 pour stdout, 2 pour stderr), sans tampon ni mise en forme. Renvoie le nombre d'octets écrits.

Synopsis
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

Description

write demande au noyau d'écrire count octets, lus à partir de buf, sur le descripteur fd. Un descripteur est un petit entier : 0 pour l'entrée standard, 1 pour la sortie standard, 2 pour la sortie d'erreur, puis ceux que renvoient open, pipe ou socket.

C'est l'appel qui se trouve sous printf(3) et puts(3), sans ce qu'ils ajoutent. Aucun tampon dans ton processus : quand write revient, les octets sont entre les mains du noyau. Aucune mise en forme : write ne connaît ni les chaînes ni les nombres, seulement des octets. Pour afficher un entier, il faut d'abord le convertir en chiffres toi-même.

Valeur de retour

Le nombre d'octets réellement écrits, ou -1 en cas d'erreur, avec la cause dans errno. Ce nombre peut être plus petit que count, par exemple quand le disque est plein ou qu'un signal interrompt l'écriture en cours de route. Un programme qui doit tout envoyer rappelle write avec le reste, dans une boucle.

Pièges

  • count est une taille en octets, pas une longueur de chaîne. write(1, s, sizeof s) sur un char * envoie 8 octets sur une machine 64 bits, la taille du pointeur. Pour une chaîne, utilise strlen(s).

  • write n'ajoute pas de \n et ne s'arrête pas au '\0' : write(1, "abc", 4) envoie aussi l'octet nul.

  • Mélanger write et printf sur la même sortie mélange l'ordre d'affichage dès que stdout n'est plus un terminal, parce que printf garde son texte en tampon. La démonstration est dans printf n'affiche rien avant un crash.

  • Un caractère accentué compte pour plusieurs octets en UTF-8 : strlen les compte bien, un nombre écrit à la main se trompe facilement.

Exemple

write.c
#include <string.h>#include <unistd.h>
int main(void){    const char *msg = "connexion établie\n";    ssize_t n;
    n = write(1, msg, strlen(msg));    if (n == -1)        return 1;    write(2, "fini\n", 5);    return 0;}
Terminal
$ gcc -Wall -Wextra -g write.c -o write$ ./writeconnexion établiefini$ ./write > out.txtfini$ cat out.txtconnexion établie

La redirection > ne concerne que le descripteur 1 : le message envoyé sur le 2 reste à l'écran.

C

write_str

Écris write_str, qui envoie une chaîne sur le descripteur 1 avec write, un caractère par appel, sans l'octet nul final.

Ouvrir l'exercice

À toi d'écrire le code.