Je regarde la sortie strace d'un processus bash en cours d'exécution connecté à un terminal, à des fins éducatives.
Mon processus bash a le PID 2883.
J'écris
[OP@localhost ~]$ strace -e trace=openat,read,write,fork,vfork,clone,execve -p 2883 2> bash.strace
Dans un terminal. J'entre alors dans mon processus bash, et j'ai l'interaction suivante:
[OP@localhost ~]$ ls
En regardant la sortie, je vois
strace: Process 2883 attached
read(0, "l", 1) = 1
write(2, "l", 1) = 1
read(0, "s", 1) = 1
write(2, "s", 1) = 1
read(0, "\r", 1) = 1
write(2, "\n", 1) = 1
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fec6b1d8e50) = 3917
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
write(1, "\33]0;OP@localhost:~\7", 23) = 23
write(2, "[OP@localhost ~]$ ", 22) = 22
...
Je suis confus aux deux dernières lignes. Il semble que bash tente d'écrire deux invites shell? Que se passe t-il ici?
cat
, il y a deux différences: il lit l'entrée ligne par ligne, et bien qu'il répète son entrée à stdout, je vois l'entrée deux fois (une fois lorsque je tape et une fois lorsque cat la fait écho).^A
(Ctrl-A) ou les divers caractères spéciaux sont pressés. En outre, il désactive l'écho du terminal, afin qu'il puisse décider quoi produire pour chaque caractère d'entrée particulier (encore une fois, TAB ne génère généralement pas de TAB.) Necat
fait rien de tout cela. Si vous le faites, essayez de lancerdash
, qui ne fait aucune manipulation en ligne de commande.read()
à ne lire qu'un octet à la fois est qu'il ne peut pas lire au-delà d'une nouvelle ligne. La nouvelle ligne peut provoquer l'exécution d'un programme externe, qui peut également lire à partir de la même entrée. (Et ce programme devrait être capable de lire tous les caractères après la nouvelle ligne.) S'il n'avait pas à s'en soucier, il pourrait appelerread()
avec une limite plus grande, et avec le terminal en mode brut, il obtiendrait généralement l'entrée un personnage à la fois. (Celaread()
avec un tampon plus important peut toujours renvoyer les deux lignes dans le même appel. Je ne pense pas qu'il y ait une garantie quiread()
serait toujours revenir une seule ligne en mode cuit.