Adloun

Le tube, et qui meurt en premier

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 8 — Mémoire, fichiers et entrées-sorties

Énoncé

Le programme ./geninf écrit les entiers sans jamais s'arrêter. Pourquoi ./geninf | head -3 se termine-t-il ? Avec quel code de sortie ?

Corrigé

Il se termine, et vite : seconde mesurée, trois lignes affichées. Les codes de sortie mesurés sont 141 pour le générateur, 0 pour head.

Le déroulement, dans l'ordre :

Ce que ce code de sortie enseigne. Le générateur n'a pas décidé de s'arrêter : il a été arrêté. C'est le mécanisme qui rend les tubes utilisables sur des flux infinis ou immenses — ./enorme | head -3 ne lit pas le fichier entier. Un programme qui ne veut pas mourir ainsi peut ignorer SIGPIPE, mais il doit alors vérifier ce que rend chaque printf, et l'immense majorité ne le fait pas.

Le second effet, moins visible. Le tube a une capacité bornée (quelques dizaines de kilo-octets). Si le lecteur est lent, l'écrivain se bloque une fois le tube plein, et repart quand de la place se libère. Les deux programmes se régulent donc l'un l'autre, sans se connaître et sans mémoire proportionnelle aux données : c'est ce qui permet à ./generer | ./filtrer | ./compter de traiter un téraoctet dans quelques kilo-octets de mémoire.

La leçon de conception, déjà donnée dans le cours : un programme qui lit stdin et écrit stdout se compose avec tous les autres. Un programme qui ouvre lui-même "entree.txt" ne se compose avec rien — et ne bénéficie ni de l'arrêt anticipé, ni de la régulation.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.