Qual é a motivação dessa condição se void serial8250_tx_chars(struct uart_8250_port *up)
?
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
Está presente desde o Linux 1.1.13 (maio de 1994) e se repete na maioria dos drivers UART.
Antecedentes: Linux 3.4.91 personalizado, sistema incorporado no ARMv7, a porta UART 0 está configurada para 38400 baud, FIFO de 16 bytes para E / S. Nada disso pode ser alterado em nossa configuração.
Ao imprimir muito no console via UART, o buffer interno de 4kB ( UART_XMIT_SIZE
) é preenchido e paralisa o processo de espaço do usuário até que o buffer seja esvaziado (o que leva um segundo a 38400 baud!). Então esse comportamento se repete. Isso ocorre porque a função n_tty_write()
entra em suspensão quando o buffer está cheio e não é despertada por um longo tempo devido à condição questionável acima.
Eu consideraria mais natural e eficiente se essa verificação fosse simplesmente removida. Os printfs preenchiam o buffer o mais rápido possível e continuavam na velocidade em que o buffer está sendo esvaziado , em vez do processamento de estouro que estou observando.
Funciona bem no meu ambiente, mas certamente estou perdendo ou entendendo algo errado. Deve haver uma razão para a implementação atual. Existem efeitos colaterais se eu remover essa condição?
Como uma pergunta secundária: existem opções de configuração para ajustar esse comportamento, por exemplo, para que printf sempre retorne imediatamente e descarte a saída se o buffer estiver cheio?
Respostas:
É uma medida de eficiência. A CPU roda muito mais rápido que a porta serial que, se o kernel permitir que o processo do espaço do usuário seja executado toda vez que houver um pouco de espaço no buffer, ele terminará fazendo uma viagem ao espaço do usuário e retornando a cada byte de dados. Isso desperdiça muito tempo de CPU:
O teste acima nem sequer lê e grava um dispositivo real: a diferença de tempo inteiro é a frequência com que o sistema oscila entre o espaço do usuário e o kernelspace.
Se o espaço do usuário não quiser ser retido, ele poderá usar E / S sem bloqueio ou verificar
select()
se há uma chamada para verificar se há espaço para gravar no dispositivo ... e, se não houver, pode despejar o restante em um buffer próprio e continue processando. É certo que isso complica as coisas, já que agora você tem um buffer que precisa liberar ... mas se estiver usando stdio, isso geralmente é verdade de qualquer maneira.fonte