¿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?
Respuestas:
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:
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.fuente