処理待機中の文字が256文字を超えると、8250 UARTドライバがTTYを起動できないのはなぜですか?

処理待機中の文字が256文字を超えると、8250 UARTドライバがTTYを起動できないのはなぜですか?

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年5月)から存在し、ほとんどのUARTドライバで繰り返されます。

背景:カスタムLinux 3.4.91、ARMv7の組み込みシステム、38400ボーレートで構成されたUARTポート0、I / O用の16バイトFIFO。私たちの設定ではこれを変更することはできません。

printfするとき非常にUARTを介してコンソールから内部4kBバッファ(UART_XMIT_SIZE)が満たされます屋台バッファがフラッシュされるまでユーザースペースプロセスを実行します(38400ボードで1秒かかります!)。その後、動作が繰り返される。n_tty_write()前述の疑わしい状況のためにバッファがいっぱいになると、その機能がスリープモードに入り、長い間目覚めないためです。

このテストを簡単に削除すると、より自然で効率的だと思います。その後、printfsはできるだけ早くバッファを埋めます。その後、バッファの空き速度に進みます。、私が観察しているバースト処理ではなく

私の環境ではうまくいきますが、明らかに何かが欠けているか誤解しています。現在の実装には理由が必要です。この状態を取り除くと副作用がありますか?

追加の質問として:printfが常にすぐに返されるようにし、バッファがいっぱいになると出力を削除するなど、この動作を調整する設定オプションはありますか?

答え1

これは効率測定です。 CPUはシリアルポートよりもはるかに速く実行され、バッファに少しのスペースがあるたびにカーネルがユーザースペースプロセスを実行できるようにすると、最終的にすべてのデータバイトに対してユーザースペースに往復します。これは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

上記のテストは、実際のデバイスを読み書きすることもありません。全体的な時間差は、システムがユーザー空間とカーネル空間の間をどれだけ頻繁にジャンプするかです。

ユーザースペースがブロックされたくない場合は、非ブロックI / Oを使用するか、呼び出しを使用してselect()デバイスに書き込むスペースがあるかどうかを確認できます。そうでない場合は、残りを次のスペースにダンプできます。独自のバッファを使用して処理を続行します。もちろん、今すぐフラッシュする必要があるバッファがあるため、状況は複雑になります。しかし、これは通常stdioを使用している場合に当てはまります。

関連情報