Quelle est la motivation de cette condition si void serial8250_tx_chars(struct uart_8250_port *up)
?
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
Il existe depuis Linux 1.1.13 (mai 1994) et se répète dans la plupart des pilotes UART.
Contexte: Linux 3.4.91 personnalisé, système embarqué sur ARMv7, le port UART 0 est configuré pour 38400 bauds, FIFO 16 octets pour les E / S. Rien de tout cela ne peut être modifié dans notre configuration.
Lorsque vous imprimez très lourdement sur la console via UART, le tampon interne de 4 Ko ( UART_XMIT_SIZE
) se remplit puis bloque le processus de l'espace utilisateur jusqu'à ce que le tampon soit vidé (ce qui prend une seconde à 38 400 bauds!). Ensuite, ce comportement se répète. En effet, la fonction se n_tty_write()
met en veille lorsque le tampon est plein et n'est pas réveillée pendant une longue période en raison de la condition discutable ci-dessus.
Je trouverais cela plus naturel et efficace si ce chèque était simplement supprimé. Ensuite, les printfs rempliraient le tampon le plus rapidement possible, puis continueraient à la vitesse à laquelle le tampon est vidé , plutôt que le traitement par rafale que j'observe.
Cela fonctionne bien dans mon environnement, mais je manque sûrement quelque chose ou je me méprends. Il doit y avoir une raison à la mise en œuvre actuelle. Y a-t-il des effets secondaires si je supprime cette condition?
Comme question secondaire: existe-t-il des options de configuration pour régler ce comportement, par exemple pour que printf revienne toujours immédiatement et rejette la sortie si le tampon est plein?
Réponses:
C'est une mesure d'efficacité. Le processeur s'exécute tellement plus rapidement que le port série que si le noyau laissait le processus de l'espace utilisateur s'exécuter à chaque fois qu'il y avait un peu de place dans le tampon, il finirait par faire un voyage dans l'espace utilisateur et revenir pour chaque octet de données. C'est très gaspillant du temps CPU:
Le test ci-dessus n'est même pas en train de lire et d'écrire un véritable appareil: la différence de temps totale est la fréquence à laquelle le système rebondit entre l'espace utilisateur et l'espace noyau.
Si l'espace utilisateur ne veut pas être bloqué, il peut utiliser des E / S non bloquantes, ou il peut vérifier utiliser un
select()
appel pour voir s'il y a de la place pour écrire sur le périphérique ... et s'il n'y en a pas, il peut vider le reste dans une mémoire tampon et continuer le traitement. Certes, cela complique les choses, puisque maintenant vous avez un tampon que vous devez vider ... mais si vous utilisez stdio, c'est généralement vrai de toute façon.la source