Какова мотивация этого if-условия в void serial8250_tx_chars(struct uart_8250_port *up)
?
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
Он существует с Linux 1.1.13 (май 1994 г.) и повторяется в большинстве драйверов UART.
Справочная информация: настроенный Linux 3.4.91, встроенная система на ARMv7, порт 0 UART настроен на 38400 бод, 16-байтовый FIFO для ввода-вывода. Ничто из этого не может быть изменено в нашей настройке.
При очень интенсивной печати на консоли через UART внутренний 4kB-buffer ( UART_XMIT_SIZE
) заполняется, а затем останавливает процесс пользовательского пространства до тех пор, пока не будет очищен буфер (который занимает одну секунду со скоростью 38400 бод!). Затем это поведение повторяется. Это происходит потому, что функция n_tty_write()
переходит в спящий режим, когда буфер заполнен, и долго не просыпается из-за сомнительного условия, описанного выше.
Я бы нашел более естественным и эффективным, если бы эта проверка была просто удалена. Затем printfs заполняют буфер так быстро, как только могут, и затем продолжают со скоростью, с которой очищается буфер , а не с обработкой пакета, которую я наблюдаю.
Это прекрасно работает в моей среде, но, конечно, я что-то упускаю или неправильно понимаю. Должна быть причина для текущей реализации. Есть ли побочные эффекты, если я уберу это условие?
В качестве дополнительного вопроса: есть ли параметры конфигурации для настройки этого поведения, например, чтобы printf всегда возвращал немедленно и отбрасывал вывод, если буфер заполнен?
Ответы:
Это мера эффективности. Процессор работает намного быстрее, чем последовательный порт, поэтому, если ядро позволяет процессу пользовательского пространства запускаться каждый раз, когда в буфере остается немного места, он в конечном итоге совершает поездку в пользовательское пространство и обратно для каждого байта данных. Это очень расточительное время процессора:
Вышеупомянутый тест даже не читает и не записывает реальное устройство: разница во времени заключается в том, как часто система отскакивает от пространства пользователя от пространства ядра.
Если пользовательское пространство не хочет удерживаться, оно может использовать неблокирующий ввод-вывод или может проверить использование
select()
вызова, чтобы увидеть, есть ли место для записи на устройство ... а если нет, оно может сбросить остаток в свой собственный буфер и продолжить обработку. Надо признать, что это усложняет ситуацию, поскольку теперь у вас есть буфер, который вы должны очистить ... но если вы используете stdio, это в общем случае так или иначе.источник