Le contrôle de flux (= prise de contact (handshaking) = ralentissement) permet d'empêcher un flux d'octets trop rapide de dépasser un terminal, un ordinateur, un modem ou un autre périphérique. Le dépassement est le fait qu'un périphérique ne puisse pas traiter ce qu'il reçoit assez rapidement et ainsi perd des octets et/ou fait d'autres erreurs sérieuses. Ce que fait le contrôle de flux est d'arrêter le flux d'octets jusqu'à ce que le terminal (par exemple) soit prêt à recevoir des octets supplémentaires. Le contrôle de flux envoie un signal pour arrêter le flux dans la direction opposée au flux des données qu'il veut arrêter. Le contrôle de flux doit être lancé à la fois sur le terminal et sur l'ordinateur.
Il y a deux types de contrôle de flux : matériel et logiciel (Xon/Xoff ou DC1/DC3). Le contrôle de flux matériel utilise des fils de signaux dédiés comme RTS/CTS ou DTR/DSR alors que le contrôle de flux logiciel se signale en envoyant les octets de contrôle DC1 ou DC3 dans les fils de données normaux. Pour le contrôle de flux matériel, le câble doit être câblé correctement.
Le flux des octets de données dans le câble entre deux ports série est bidirectionnel, il y a donc deux flux (et deux fils) différents à considérer :
Vous pouvez vous demander : "Pourquoi ne pas envoyer les données à une vitesse suffisamment petite pour que le périphérique ne soit pas dépassé et que le contrôle de flux ne soit ainsi plus nécessaire ?" Ceci est possible mais c'est en général bien plus lent que d'envoyer les données plus rapidement et d'utiliser le contrôle de flux. Une raison à ceci est qu'on ne peut pas positionner la vitesse du port série à n'importe quelle vitesse comme 14.500, puisqu'un nombre limité de choix est disponible. Le meilleur choix est de sélectionner une vitesse légèrement plus élevée que ce que peut soutenir le périphérique et d'utiliser ensuite le contrôle de flux pour que les choses fonctionnent correctement.
Si on décide de ne pas utiliser le contrôle de flux, la vitesse doit alors être suffisamment basse pour pallier à la pire des situations. Pour un terminal, cela arrive quand on envoie des séquences d'échappement pour effectuer des tâches complexes qui prennent plus de temps qu'à l'accoutumée. Dans le cas d'un modem (avec la compression de données mais pas de contrôle de flux) la vitesse de l'ordinateur au modem doit être suffisamment basse pour que cette même vitesse soit utilisable sur la ligne téléphonique, puisque dans le pire des cas les données sont aléatoires et ne peuvent être compressées. Si on ne pouvait pas utiliser de contrôle de flux, la vitesse (avec la compression de données activée) ne serait pas plus rapide que si on n'utilisait pas de compression du tout.
Les buffers (mémoires tampons) aident à gérer les situations catastrophes de courte durée. Le tampon stocke les octets qui arrivent trop rapidement pour être traités tout d'un coup, et les garde pour les traiter plus tard.
Une autre manière de gérer une situation "catastrophe" (sans utiliser de contrôle de flux ni de tampon) est d'ajouter un groupe de nulls (octets de valeur zéro) aux séquences d'échappement. Quelquefois on utilise des DEL à la place, à condition qu'ils n'aient pas d'autre fonction. Voyez reconnaître DEL.
La séquence d'échappement permet au terminal de commencer à faire quelque
chose, et pendant que le terminal est occupé à le faire, il reçoit une
poignée de nulls qu'il ignore. Quand il reçoit le dernier null, il a terminé
sa tâche et est prêt pour la commande suivante. C'est ce qu'on appelle le
remplissage de zéros (null padding). Ces nulls étaient autrefois appelés des
"caractères de remplissage". Ces nulls sont ajoutés simplement pour "perdre"
du temps, mais ce n'est pas tout à fait perdu puisque le terminal est en
général occupé à faire autre chose pendant que les nulls sont reçus. On
utilisait beaucoup cette méthode dans le passé avant que le contrôle de flux
ne devienne populaire. Pour être efficace, il fallait ajouter le nombre exact
de nulls et trouver la bonne valeur est difficile. On le faisait souvent par
essais successifs et tâtonnements puisque les manuels de terminaux n'étaient
pas de grand secours. Si le contrôle de flux ne fonctionne pas correctement
ou n'est pas implémenté, le remplissage est une solution. Certaines options
de la commande stty
concernent le remplissage.
On peut se demander comment le débordement est possible sur un port série puisqu'à la fois les ports série d'envoi et de réception servant à la transmission d'octets de données sont paramétrés pour la même vitesse (en bits/s) comme 19200. La raison est que bien que l'électronique du port série récepteur peut gérer la vitesse du flux arrivant, le matériel/logiciel qui prend et traite les octets du port série ne peut pas toujours se débrouiller avec une vitesse de flux élevée.
L'une des causes de ceci est que le tampon matériel du port série est assez petit. Les anciens ports série avaient une taille de tampon matériel d'un octet seulement (à l'intérieur de la puce UART). Si cet unique octet de données reçu dans le tampon n'est pas enlevé (pris) par des instructions CPU avant que l'octet suivant n'arrive, cet octet est perdu (le tampon est débordé). Les UART récents, par exemple la plupart des 16550A, possèdent des tampons de 16 octets (mais peuvent être paramétrés pour émuler un tampon d'un octet) et sont moins susceptibles d'être débordés. On peut le paramétrer pour envoyer une interruption quand le nombre d'octets dans son tampon atteint 1, 4, 8 ou 14 octets. C'est le travail d'une autre puce dans l'ordinateur (généralement la puce principale CPU pour un ordinateur) de retirer ces octets entrants de ce petit tampon matériel et de les traiter (ainsi que d'effectuer d'autres tâches).
Quand le contenu de ce petit tampon matériel de réception atteint la limite spécifiée (un octet pour les vieux UART) une interruption est levée. L'ordinateur interrompt alors ce qu'il était en train de faire et une routine fait une vérification pour déterminer ce qui vient de se passer. Il détermine finalement qu'il doit retirer un octet (ou plusieurs) du tampon du port série. Il prend cet (ces) octet(s) et les met dans un tampon plus grand (un autre tampon pour le port série) que le noyau maintient dans la mémoire principale. Pour le tampon de transmission, le matériel série génère une interruption quand le tampon est vide (ou presque vide) pour dire à la CPU de mettre quelques octets supplémentaires dans ce tampon afin de les envoyer.
Les terminaux possèdent aussi des ports série et des tampons similaires à ceux de l'ordinateur. Puisque le flux de données des octets vers le terminal est en général plus grand que le flux dans la direction opposée du clavier vers l'ordinateur hôte, le terminal a plus de chance de souffrir du débordement. Bien sûr, si vous utilisez un ordinateur comme terminal (par émulation), il est à son tour sujet au débordement.
Les situations risquées où le débordement est très probable sont : 1. quand un autre processus a désactivé les interruptions (pour un ordinateur), 2. quand le tampon du port série dans la mémoire principale (ou dans celle du terminal) est prête à déborder.
Quand le récepteur est sur le point d'être débordé par les octets entrants, il envoie un signal à l'expéditeur pour arrêter l'envoi. C'est le contrôle de flux et les signaux de contrôle de flux sont toujours envoyés dans la direction opposée au flux de données qu'ils contrôlent (bien que ce ne soit pas dans le même canal ou le même fil). Ce signal peut être soit un caractère de contrôle (^S = DC3 = Xoff) envoyé comme un octet de données ordinaire sur la ligne de données (signalement dans la bande), soit une transition de tension du positif au négatif dans le fil de signal dtr-vers-cts (ou autre ; signalement hors-bande). L'utilisation de Xoff est appelée "contrôle de flux logiciel" et l'utilisation du saut de tension dans un fil de signal dédié (à l'intérieur du câble) est appelée contrôle de flux matériel.
Avec les terminaux, le cas le plus commun "d'arret d'envoi", est quand le terminal ne peut pas suivre avec les caractères qui lui sont envoyés et qui en conclut par un "arret" du PC. Un autre cas, est quand quelqu'un presse control-S. Un autre cas un peu moin commun, est l'opposé, quand le PC ne peut plus suivre votre vitesse de frappe et dit au terminal d'arrêter l'envoi. Le terminal "bloque" le clavier et un message ou une lumière devrait vous informer que le clavier est bloqué. Tout ce que vous tapez sur un clavier bloqué est ignoré.
Le terme "bloqué" est aussi quelque fois utilisé pous les cas où l'on dit à l'ordinateur d'arrêter d'envoyer à un terminal. Le clavier n'est pas bloqué, afin que tout ce que vous tapez soit envoyé à l'ordinateur, mais puisque l'ordinateur ne peut rien vous renvoyer, les caractères que vous tapez ne s'affichent pas sur l'écran et il peut sembler que le clavier est bloqué. Le défilement est bloqué (scroll lock) mais le clavier n'y est pas.
Quand le récepteur a rattrapé son retard dans le traitement et est prêt à recevoir plus d'octets de données il envoie un signal à l'envoyeur. Pour le contrôle de flux logiciel ce signal est le caractère de contrôle ^Q = DC1 = Xon qui est envoyé sur la ligne de données normale. Pour le contrôle de flux matériel la tension dans une ligne de signal passe de négative (niée) à positive (affirmée). Si on dit à un terminal de reprendre la transmission le clavier est alors débloqué et prêt à être utilisé.
Certains terminaux anciens n'offrent pas de contrôle de flux matériel alors que d'autres offraient un assortiment varié de broches diverses sur le port série pour le faire. Pour une liste des differentes borches, aller voir Brochage standard d'un cable null-modem. La broche la plus en vogue actuellement semble être la broche DTR (ou les broches DTR et DSR ensemble).
Les PC Linux utilisent RTS/CTS mais le contrôle de flux DTR/DSR (utilisé par certains terminaux) se comporte de la même manière. Le contrôle de flux DTR (dans une seule direction et aussi utilisé par certains terminaux) n'est que la partie DTR du contrôle de flux DTR/DSR.
RTS/CTS utilise les broches RTS et CTS sur le connecteur série (EIA-232). RTS veut dire "Request To Send" (demande d'envoyer). Quand cette broche reste en position haute (tension positive) sur le récepteur cela veut dire : continuez de m'envoyer des données. Si RTS passe en position basse (la tension devient négative), cela nie "demande d'envoyer", ce qui veut dire : arrêtez d'envoyer. Quand le récepteur est prêt à recevoir plus de données, il relance RTS, demandant à l'autre côté de reprendre l'envoi. Pour les ordinateurs et les terminaux (tous les deux des équipements terminaux) la broche RTS envoie le signal de contrôle de flux à la broche CTS (Clear To Send, prêt à envoyer) de l'autre côté du câble. C'est-à-dire que la broche RTS à un bout du câble est reliée à la broche CTS à l'autre bout du câble.
Pour un modem (équipement de connexion) le principe est différent puisque la broche RTS du modem reçoit le signal et sa broche CTS l'envoie. Alors que ceci peut sembler déroutant, il y a des raisons historiques correctes pour l'expliquer, raisons qui sont trop compliquées pour en discuter ici.
Les terminaux disposent en général du contrôle de flux DTR ou DTR/DSR. Le contrôle de flux DTR est le même que le contrôle de flux DTR/DSR mais il est unidirectionnel et la broche DSR n'est pas utilisée. En ce qui concerne le contrôle de flux DTR/DSR sur un terminal, le signal DTR est comme le signal envoyé de la broche RTS, et la broche DSR est simplement comme la broche CTS.
Certains terminaux n'utilisent que le contrôle de flux DTR. C'est un contrôle de flux unidirectionnel uniquement pour empêcher le terminal d'être dépassé. Il ne protège pas l'ordinateur de quelqu'un qui tape trop vite pour que l'ordinateur puisse gérer la situation. Dans un câble null modem classique la broche DTR du terminal est reliée à la broche DSR de l'ordinateur. Linux, par contre, ne supporte pas le contrôle de flux DTR/DSR (bien que des pilotes pour des cartes multiports peuvent supporter le contrôle de flux DTR/DSR). Un moyen de contourner ce problème est simplement de relier la broche DTR à la broche CTS sur l'ordinateur et d'activer le contrôle de flux RTS/CTS (stty crtscts). Le fait que ce soit unidirectionnel ne changera rien tant que l'hôte n'est pas dépassé par votre vitesse de frappe et ne lâche RTS en une vaine tentative pour bloquer votre clavier. Voyez blocage du clavier. Pour obtenir le contrôle de flux DTR/DSR (si votre terminal supporte ce type de contrôle de flux bidirectionnel) vous faites ce qui est décrit ci-dessus. Mais vous connectez aussi la broche DSR sur le terminal à la broche RTS sur l'ordinateur. Vous êtes alors protégé si vous tapez trop rapidement.
Ce qui est déroutant est que l'utilisation d'origine de RTS veut dire à peu près le contraire de l'explication précédente ci-dessus. La signification d'origine est : je demande à vous envoyer (I Request To Send to you). Cette requête était destinée à être envoyée d'un terminal (ou d'un ordinateur) vers un modem qui, s'il décidait d'accorder la requête, renvoyait un CTS affirmatif à partir de sa broche CTS vers la broche CTS de l'ordinateur : vous êtes autorisé à m'envoyer (You are Cleared To Send to me). Notez qu'au contraire du contrôle de flux RTS/CTS bidirectionnel du modem, ceci ne protège le flux que dans une direction : de l'ordinateur (ou du terminal) vers le modem.
Pour de vieux terminaux, RTS peut avoir cette signification et devient positif quand le terminal doit envoyer des données. L'utilisation ci-dessus est une forme de contrôle de flux puisque si le modem veut que l'ordinateur arrête d'envoyer il lâche CTS (connecté au CTS de l'ordinateur) et l'ordinateur arrête d'envoyer.
Les vieux terminaux à sortie papier peuvent avoir une broche de canal inversé (comme la broche 19) qui se comporte comme la broche RTS dans le contrôle de flux RTS/CTS. Cette broche passera aussi en négatif s'il n'y a plus de papier ou de ruban. Il est souvent possible de relier cette broche à la broche CTS de l'ordinateur hôte. Il peut y avoir un petit interrupteur pour positionner la polarité de ce signal.
Certains pensent que le contrôle de flux matériel est fait par le matériel mais (sauf si vous utilisez une carte série intelligente avec plusieurs ports série) c'est en réalité votre système d'exploitation qui s'en charge. Les puces UART et le matériel associé ne connaissent en général rien du contrôle de flux matériel. Quand un signal de contrôle de flux matériel est reçu, le fil du signal inverse la polarité. Ce changement d'état est enregistré dans un registre de port série qui est vérifié par le pilote série avant de mettre les octets dans les tampons materiels de 16 octets. Si le fil du control de flux dit "stop", il n'y a plus d'octets ajoutés et le flux sortant des lignes séries s'arrete.
Il y'a un autre moyen qui aurait pu être implementer depuis que la polarité s'inverse, le materiel aurait pu être configuré pour envoyer un signal éléctrique d'interruption au processeur. Alors le processeur arreterait ce qu'il était en train de faire, se brancherait a un sous-programme de service du pilote série, verifierait les registres dans lesquels le port serie a laissé des traces pour trouver ce qui s'est passé, et fais un rapport, pour ne pas redémarrer le flux apres que le sous programme de service soit quitté. Cela doit être un peu plus efficace, mais il semble que Linux n'agisse pas comme ca. A mon avis.
Noter qu'avec l'une ou l'autre des methodes, le flux d'octets s'arrette quasiment instantanement. Cependant tous les octets (jusqu'à 16) qui étaient déjà dans le tampon de transmission matériel du port série seront encore transmis. Utiliser un control de flux logiciel requiert que chaque octet arrivant soit verifié pour voir si c'est un octet "eteint". Ces octets sont retardés en passant à travers le tampon de réception de 16 octets. Si l'octet "éteint" était le premier octet dans ce tampon, il pourrait y avoir une attente le temps que 15 octets soient reçus. Alors les 16 octets lus seraient obtenus et l'octet "éteint" trouvé. Cette attente supplementaire n'arrive pas avec un control de flux materiel.
Ceci est aussi du contrôle de flux matériel et nécessite un pilote de périphérique qui sait le traiter. Les octets sont envoyés par paquets (grâce au port série asynchrone), chaque paquet étant terminé par un caractère de contrôle ETX (End of Text, fin de texte). Quand le terminal reçoit un ETX il attend jusqu'à ce qu'il soit prêt à recevoir le paquet suivant et retourne alors un ACK (Acknowledge, acquittement). Quand l'ordinateur reçoit le ACK, il envoie le paquet suivant. Et ainsi de suite. Ceci n'est pas supporté par Linux ?? Certains terminaux HP utilisent la même méthode mais utilisent ENQ au lieux de ETX.