¿Por qué el controlador 8250 UART no activa TTY si hay más de 256 caracteres pendientes?

8

¿Cuál es la motivación de esta condición si void serial8250_tx_chars(struct uart_8250_port *up)?

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
    uart_write_wakeup(port);

Ha estado allí desde Linux 1.1.13 (mayo de 1994) y se repite en la mayoría de los controladores UART.

Antecedentes: Linux 3.4.91 personalizado, sistema integrado en ARMv7, el puerto UART 0 está configurado para 38400 baudios, FIFO de 16 bytes para E / S. Nada de esto se puede cambiar en nuestra configuración.

Cuando printf-ción muy gran medida de la consola a través de UART, el 4kB-buffer interno ( UART_XMIT_SIZE) se llena y luego se atasca el proceso de espacio de usuario hasta que se vacía la memoria intermedia (que tiene un segundo a 38400 baudios!). Entonces este comportamiento se repite. Esto se debe a que la función se n_tty_write()pone en suspensión cuando el búfer está lleno y no se activa durante mucho tiempo debido a la cuestionable condición anterior.

Me resultaría más natural y eficiente si esta verificación simplemente se eliminara. Luego, printfs llenaría el búfer lo más rápido que pudiera y luego continuaría a la velocidad a la que se vacía el búfer , en lugar del proceso de ráfaga que estoy observando.

Funciona bien en mi entorno, pero seguramente me falta o no entiendo algo. Debe haber una razón para la implementación actual. ¿Hay algún efecto secundario si elimino esa afección?

Como pregunta secundaria: ¿hay opciones de configuración para ajustar este comportamiento, por ejemplo, para que printf siempre regrese inmediatamente y descarte la salida si el búfer está lleno?

Hans W. Heckel
fuente
Sin saber demasiado sobre esto, mi presentimiento es el siguiente: esta es una configuración de consola serie Linux ordinaria. Trabajé con aquellos en el hardware estándar x86. Para las conexiones seriales directas, siempre tuve que usar el control de flujo de hardware. Puede ser una idea
vasquez
1
Es probable que haya una diferencia de eficiencia. ¿Por qué no simplemente configurar WAKEUP_CHARS en algo como UART_XMIT_SIZE - 128?
James Youngman
@JamesYoungman De hecho, eso es lo que terminé haciendo también. ¡Salud!
Hans W. Heckel

Respuestas:

2

Es una medida de eficiencia. La CPU funciona mucho más rápido que el puerto serie que si el kernel deja que el proceso de espacio de usuario se ejecute cada vez que haya un poco de espacio en el búfer, terminaría haciendo un viaje al espacio de usuario y viceversa por cada byte de datos. Eso es un desperdicio de tiempo de CPU:

$ time dd if=/dev/zero of=/dev/null bs=1 count=10000000
10000000+0 records in
10000000+0 records out
10000000 bytes (10 MB, 9.5 MiB) copied, 5.95145 s, 1.7 MB/s

real    0m5.954s
user    0m1.960s
sys     0m3.992s

$ time dd if=/dev/zero of=/dev/null bs=1000 count=10000
10000+0 records in
10000+0 records out
10000000 bytes (10 MB, 9.5 MiB) copied, 0.011041 s, 906 MB/s

real    0m0.014s
user    0m0.000s
sys     0m0.012s

La prueba anterior ni siquiera está leyendo y escribiendo un dispositivo real: la diferencia de tiempo es la frecuencia con la que el sistema rebota entre el espacio de usuario y el espacio de kernel.

Si el espacio de usuario no quiere retrasarse, puede usar E / S sin bloqueo, o puede verificar usar una select()llamada para ver si hay espacio para escribir en el dispositivo ... y si no lo hay, puede volcar el resto en un búfer propio y continuar procesando. Es cierto que eso complica las cosas, ya que ahora tiene un búfer que tiene que vaciar ... pero si está usando stdio, eso generalmente es cierto de todos modos.

Jander
fuente
Esto respalda el comentario de @James sobre la eficiencia anterior. Ahora tiene mucho más sentido para mí. Gracias, también por los números!
Hans W. Heckel
Cabe señalar que desde el kernel 2.6, esta pregunta hace referencia al código que a menudo aparece en los controladores de capa inferior (por ejemplo, un controlador UART). Estos controladores proporcionan la capa superior, serial_core, los medios para interactuar con el hardware. Es el núcleo serial el que realmente interactúa con el espacio del usuario (a menos que el controlador de hardware implemente sus propios ioctls o algo similar). Creo que la respuesta de los encuestados aún se mantiene.
Andrew Falanga