1

Linux (Ubuntu 12.04) でシリアル ポートを読み書きしようとしています。このポートでは、特定のタスクが完了するたびに、相手側のマイクロコントローラーが 1 または 3 バイトを爆破します。デバイスへの読み取りと書き込みは正常に実行できますが、問題は、現在、読み取りが少し「危険」であることです。

do
{
    nbytes = read(fd, buffer, sizeof(buffer));
    usleep(50000);
} while(nbytes == -1);

つまり、デバイスが何を送信しているかを簡単に監視するために、バッファを 0.5 秒ごとにポーリングします。空の場合は、このループでアイドル状態になります。何かまたはエラーを受け取ると、キックアウトします。次に、一部のロジックが 1 つまたは 3 つのパケットを処理し、それを端末に出力します。通常、0.5 秒は、何かがバッファーに完全に表示されるのに十分な長さのウィンドウですが、最終的にそれを見る人間が遅いとは思わないほど速いです。

「いつも」がキーワードです。途中でバッファを読み取った場合、3バイトを爆破します。私は悪い読み取りを取得します。バッファには 1 バイトまたは 2 バイトが含まれ、パケット処理で拒否されます (3 バイト パケットの最初のパケットをキャッチすると、意図的に送信された 1 バイト値にはなりません)。

私が検討/試した解決策:

  1. 一度に 1 バイトずつ読み込み、3 バイト送信の一部である場合は追加のバイトを供給することを考えました。ただし、これにより、できれば回避したいいくつかの醜いループが作成されます (read() は、直前の読み取りのバイト数のみを返すため)。

  2. 自分のバッファーにロードする前に、現在バッファーにあるバイト数を確認するために、0 バイトを読み取ろうとしました (例: nbytes = read(fd, buffer, 0);)。 0 を返します。

自分のバッファにロードする前にポートバッファの内容を覗くことができれば、私の問題の多くは簡単に解決できるようです。しかし、 read() は、読み取るように指示したバイト数まで破壊的です。

送信を受信して​​いる途中ではなく、ユーザーに遅く見えないように十分に高速に、このバッファから読み取るにはどうすればよいですか? 私のシリアル メッセンジャーは送信側スレッドと受信側スレッドに分かれているため、プログラム ループがどこかでブロックされ、残りの半分が無視されることを心配する必要はありません。

助けてくれてありがとう。

4

3 に答える 3

3

パケット処理を修正します。このようなインスタンスでは常にステート マシンを使用することになります。そのため、部分的なメッセージを受け取った場合に、処理を中断した場所を (ステートフルに) 記憶し、残りのパケットが到着したときに再開できるようにします。

通常、他の処理に進む前に、パケットの最後でチェックサムを検証する必要があるため、「処理を中断した場所」は常に「チェックサムを待っている」ことになります。しかし、追加のデータが到着したときに使用するために、部分的なパケットを保存します。

ドライバー バッファーを覗き見ることはできませんが、これらすべてのバイトを独自のバッファーに読み込み (C++ では adequeが適切な選択です)、必要なすべてを覗き込むことができます。

于 2013-03-30T16:11:23.433 に答える
2

送信されるメッセージのサイズを知る必要があります。これを行うには、いくつかの方法があります。

  1. メッセージの長さをメッセージの前に付けます。
  2. メッセージターミネータ、メッセージの一部にすることのできないバイト (またはバイトのシーケンス) があります。
  3. 「コマンド」を使用して長さを計算します。つまり、コマンドバイトを読み取ると、その後に続くデータの量がわかるので、その量を読み取ります。

2 番目の方法は、メッセージ ターミネータ シーケンスを取得し、次のバイトが新しいメッセージであることが確実になるまで読み取るため、同期が外れる可能性がある場合に最適です。

もちろん、これらの方法を組み合わせることもできます。

于 2013-03-30T15:02:43.090 に答える