2009-08-31 8 views
7

私は、小さな組み込みシステム(マルチドロップ、rs485タイプのもの)のための単純なプロトコルスタックに取り組んでいます。このスタックにおいて、OSI層の後loselyモデル:レイヤードプロトコルスタックで大きなバッファを処理するにはどうすればよいですか?

  1. アプリケーション
  2. ネットワーク
  3. 物理データリンク
  4. (シリアルドライバ)

各層が包み込み、それ自身のヘッダ/フッタ部を有していますその上にあるレイヤーのペイロード。

バイナリパケットを格納するために静的に割り当てられた固定サイズのブロックの独自のバッファプールを使用します。 (このアプリではmalloc/freeはありません)

他のAPIでは、データは通常、関連する長さのconstポインタとして渡されることがわかりました。このようにして、上記のレイヤのペイロードが現在のレイヤの新たに割り当てられたバッファに配置されるので、データは各レイヤでコピー操作を必要とする。

3層スタックの場合、これは2コピー操作と3つの割り当てバッファとなります。

これを実行しても、プロトコルレイヤーをきれいに分離しておく方が良いでしょうか?

説明をよりよくするために、パケットは通常約2kで、プロセッサは8Mhzで動作する小さな8ビットマイクロです。

+0

8bit micro @ 8Mhzと2kBパケット?あなたは利用可能なRAMについて言及していないが、私はパケットがかなりいっぱいになると思うだろうと私はあなたがそのようなシンプルなシステムのために非常に多くのレイヤーと抽象を作成する理由を見逃すと思います。それを「データ伝送」と「アプリケーション」に分割し、ペイロードをポインタを介してグローバルに渡します。 – Mark

+1

@マーク、そのプロトコルスタックは異なるプラットフォームで使用されますが、1つはAtmega1281で8kラムです。それは20Mhzで計時することができますが、我々は力の理由でそれをやっていません。私は懸念の分離を緩和することができますが、それは私の質問のポイントではありません。 – JeffV

+0

@マーク、あなたは2kバッファーについては正しいですが、私はそれほど大きくすることはできませんが、このアプリケーションではレイテンシの高いデータチャネル(サテライト)の方が大きいほど大きくなります。ウィンドウ処理(TCPの場合と同様)。 – JeffV

答えて

7

あなたは自分自身を次の下位層から各層の要求に空のバッファを有する、1つではなく割り当てることによってコピーを避けることができ:

  • アプリケーションレイヤは、ネットワーク層からバッファ 長さLAを要求します。
  • ネットワーク層は、データリンク層からのバッファ長LA + LNを要求する。
  • 物理層からバッファ長LA + LN + LDを要求します。
  • 物理層は、バッファをバッファプールからプルします。
  • 物理層がbuffer + phdr_lenをデータリンク層に返します。
  • データリンク層は、ネットワーク層にbuffer + phdr_len + dhdr_lenを返します。
  • ネットワークレイヤーは、buffer + phdr_len + dhdr_len + nhdr_lenをアプリケーションレイヤーに返します。
  • アプリケーション層は、提供されたバッファ内のデータを埋め込み、送信するためにネットワーク層を呼び出します。
  • ネットワークレイヤは、ヘッダの前に付加され、送信するデータリンクレイヤを呼び出します。
  • データリンクレイヤは、ヘッダの前に付加され、送信する物理レイヤを呼び出します。
  • 物理層は、ヘッダの前に付加され、ハードウェアに渡されます。
+0

または、異なるレイヤーのヘッダーは連続している必要はありません(単一のバッファー内)。代わりに、「スキャッター・ギャザー(scatter gather)」APIを使用して異なるバッファーに入れることができます。 – ChrisW

+0

ありがとう@caf、私は可能な解決策としてこれについても考えていました。 get_buffer()呼び出しの時点で、上位層がバッファの責任を負います。バッファが適切に解放されるように何かがうまくいかない場合に備えて、send(pbuf)に加えて各層にfree_buffer()が必要です。 – JeffV

0

他のAPIでは、通常、データは関連する長さのconstポインタとして渡されることがわかりました。このようにして、上記のレイヤのペイロードが現在のレイヤの新たに割り当てられたバッファに配置されるので、データは各レイヤでコピー操作を必要とする。

私は送信バッファ用のAPIの例を挙げていると思います。

私は、このAPIを呼び出す人は、送信操作が完了したという後続の通知を受け取るまで、そのバッファを再び使用またはタッチすることができないという制限を追加すると、同じAPIを維持できると思います。 APIは暗黙的にそのバッファーの所有権を転送しています。

4

バッファ構造を作成します。最下層の最大サイズを把握した上で、最下位層に十分なバッファスペースを割り当てて、連続する各層をスタックの下側に先行させる。レイヤーが追加されると、各レイヤーはバッファー構造内のポインターを移動します。

バッファの先頭がバッファ構造のポインタに記録されます。送信されるデータは連続バッファにあります。各レイヤーにはデータはコピーされませんでした。

下から上へ行くと、バッファー構造内のレイヤーが剥がれます。

+0

これは、バッファが1つでコピーが不要なため、最も簡単な方法です。スレーブデバイスの場合、通常、バッファは物理層に定義されます。これは、メッセージの発信元と同じです。 –

+0

異なるパケットタイプを持っている場合は、別のタイプの構造体ポインタを参照するだけです。 –

+2

この問題は、最上位層が、各下位層がどれくらい必要かを知る必要があることをOPが回避しようとしているタイトなカップリングであることが必要です(これは「プロトコル層のきれいな分離」についての言い回しです) 。 – caf

関連する問題