Was ist die Motivation für diese Wenn-Bedingung void serial8250_tx_chars(struct uart_8250_port *up)
?
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
Es ist seit Linux 1.1.13 (Mai 1994) vorhanden und wird in den meisten UART-Treibern wiederholt.
Hintergrund: angepasstes Linux 3.4.91, eingebettetes System auf ARMv7, UART-Port 0 ist für 38400 Baud konfiguriert, 16-Byte-FIFO für E / A. Nichts davon kann in unserem Setup geändert werden.
Wenn printf-ing sehr stark von der Konsole über UART, der internen 4kB-Puffer ( UART_XMIT_SIZE
) auffüllt und dann abgewürgt den Anwenderraum Prozess , bis der Puffer geleert wird (die bei 38400 Baud 1 Sekunde dauert!). Dann wiederholt sich dieses Verhalten. Dies liegt daran, dass die Funktion n_tty_write()
in den Ruhezustand wechselt, wenn der Puffer voll ist, und aufgrund des oben genannten fragwürdigen Zustands nicht lange geweckt wird.
Ich würde es natürlicher und effizienter finden, wenn dieser Scheck einfach entfernt würde. Dann würden die printfs den Puffer so schnell wie möglich füllen und dann mit der Geschwindigkeit fortfahren, mit der der Puffer geleert wird , anstatt mit der Burst-Verarbeitung, die ich beobachte.
Es funktioniert gut in meiner Umgebung, aber ich vermisse oder missverstehe sicherlich etwas. Es muss einen Grund für die aktuelle Implementierung geben. Gibt es irgendwelche Nebenwirkungen, wenn ich diesen Zustand entferne?
Als Nebenfrage: Gibt es Konfigurationsoptionen, um dieses Verhalten zu optimieren, z. B. dass printf immer sofort zurückkehrt und die Ausgabe verwirft, wenn der Puffer voll ist?
Antworten:
Es ist eine Effizienzmaßnahme. Die CPU läuft so viel schneller als die serielle Schnittstelle, dass, wenn der Kernel den Userspace-Prozess jedes Mal ausführen lässt, wenn ein wenig Platz im Puffer vorhanden ist, für jedes einzelne Datenbyte eine Reise in den Userspace und zurück erfolgt. Das verschwendet sehr viel CPU-Zeit:
Der obige Test liest und schreibt nicht einmal ein echtes Gerät: Der gesamte Zeitunterschied besteht darin, wie oft das System zwischen Benutzerbereich und Kernelbereich wechselt.
Wenn der Benutzerbereich nicht aufgehalten werden soll, kann er nicht blockierende E / A verwenden oder mithilfe eines
select()
Anrufs überprüfen , ob Platz zum Schreiben auf das Gerät vorhanden ist. Wenn dies nicht der Fall ist, kann er die Speicherausgabe sichern Rest in einen eigenen Puffer und Fortsetzung der Verarbeitung. Zugegeben, das macht die Sache komplizierter, da Sie jetzt einen Puffer haben, den Sie leeren müssen ... aber wenn Sie stdio verwenden, ist das im Allgemeinen sowieso wahr.quelle