16

Linux でシリアル ポート経由のプロトコルを実装しています。このプロトコルは要求応答スキームに基づいているため、スループットは、デバイスにパケットを送信して応答を取得するのにかかる時間によって制限されます。デバイスはほとんどが Arm ベースで、Linux >= 3.0 を実行します。往復時間を 10 ミリ秒未満に短縮するのに問題があります (115200 ボー、8 データ ビット、パリティなし、メッセージあたり 7 バイト)。

select、poll、epoll、または ioctl を使用した手動のポーリングのうち、どの IO インターフェースが最小のレイテンシーを提供してくれるでしょうか? ブロッキング IO または非ブロッキング IO はレイテンシに影響しますか?

setserial で low_latency フラグを設定してみました。でも効果は無かったようです。

レイテンシーを減らすために他にできることはありますか? 私はすべてのデバイスを制御しているため、カーネルにパッチを適用することもできますが、そうしないことをお勧めします。

- - 編集 - -

シリアル コントローラーは 16550A を使用します。

4

7 に答える 7

11

要求/応答スキームは非効率になる傾向があり、シリアル ポートですぐに表示されます。スループットに関心がある場合は、kermit ファイル送信プロトコルなどのウィンドウ化されたプロトコルを調べてください。

Andy Ross が指摘したように、実際のレイテンシはハードウェアの fifo 処理にあるため、プロトコルに固執してレイテンシを短縮したい場合は、select、poll、read のすべてでほぼ同じレイテンシが得られます。

運が良ければ、パッチを適用せずにドライバーの動作を微調整できますが、それでもドライバー コードを確認する必要があります。ただし、ARM で 10 kHz の割り込みレートを処理することは、システム全体のパフォーマンスにとって確かに良くありません...

別のオプションは、毎回 fifo しきい値に達するようにパケットをパディングすることです。また、それが fifo しきい値の問題であるかどうかも確認します。

10 ミリ秒 @ 115200 は 100 バイトを送信するのに十分なので (8N1 を想定)、おそらく low_latency フラグが設定されていないことが原因です。試す

setserial /dev/<tty_name> low_latency

tty レイヤーでデータを移動するときにカーネルで使用される low_latency フラグを設定します。

void tty_flip_buffer_push(struct tty_struct *tty)
{
         unsigned long flags;
         spin_lock_irqsave(&tty->buf.lock, flags);
         if (tty->buf.tail != NULL)
                 tty->buf.tail->commit = tty->buf.tail->used;
         spin_unlock_irqrestore(&tty->buf.lock, flags);

         if (tty->low_latency)
                 flush_to_ldisc(&tty->buf.work);
         else
                 schedule_work(&tty->buf.work);
}

観察された 10 ミリ秒のレイテンシーは、schedule_work 呼び出しが原因である可能性があります。

于 2012-10-30T09:51:27.387 に答える
7

このトピックについてさらに何人かのエンジニアと話し合った結果、この問題はユーザー空間では解決できないという結論に達しました。ブリッジを渡ってカーネル ランドに入る必要があるため、プロトコルと通信して 1 ミリ秒未満のレイテンシを実現するカーネル モジュールを実装する予定です。

- - 編集 - -

私は完全に間違っていたことがわかりました。必要なのは、カーネルのティック レートを上げることだけでした。デフォルトの 100 ティックには 10 ミリ秒の遅延が追加されました。シリアル プロセスの 1000Hz と負のナイス値により、到達したい時間動作が得られます。

于 2012-11-15T10:31:39.330 に答える
6

Linux のシリアル ポートは、Unix スタイルの端末構造に「ラップ」されているため、1 ティック ラグ、つまり 10ms が発生します。stty -F /dev/ttySx raw low_latency役立つかどうか試してください。ただし、保証はありません。

PCでは、ハードコアに行って標準シリアルポートと直接通信し、発行setserial /dev/ttySx uart noneしてシリアルポートハードウェアからLinuxドライバーをアンバインドしinb/outb、ポートレジスタを介してポートを制御できます。私はそれを試しました、それはうまくいきます。

欠点は、データが到着したときに割り込みが発生せず、レジスタをポーリングする必要があることです。頻繁。

アームデバイス側でも同じことができるはずですが、エキゾチックなシリアルポートハードウェアではもっと難しいかもしれません。

于 2013-01-22T16:21:18.573 に答える
1

これらのシステム コールはいずれも、レイテンシに影響を与えません。ユーザー空間から 1 バイトをできるだけ速く読み書きしたい場合、単純なread()/write()ペアよりもうまくいくことはありません。シリアル ストリームを別のユーザー空間プロセスからのソケットに置き換えてみて、レイテンシが改善するかどうかを確認してください。そうでない場合、問題は CPU 速度とハードウェアの制限です。

あなたのハードウェアがこれを行うことができると確信していますか? 多くのバイトに相当するレイテンシを導入するバッファ設計を備えた UART を見つけることは珍しくありません。

于 2012-10-29T17:54:56.580 に答える
0

これらの回線速度では、準備状況を確認する方法に関係なく、それほど大きな遅延は見られないはずです.

シリアル ポートが raw モードであること (つまり、「非正規読み取り」を行うこと) と、VMIN と VTIME が正しく設定されていることを確認する必要があります。キャラクター間タイマーが起動しないように、VTIME がゼロであることを確認する必要があります。おそらく、VMIN を 1 に設定することから始めて、そこから調整します。

syscall のオーバーヘッドは、回線上の時間と比較して何もないため、select() と poll() などで違いが生じる可能性はほとんどありません。

于 2012-10-30T10:15:57.057 に答える