TL

組込みTCP/IPスタック

数十KBのRAMでTCP/IPを動かす勘どころが掴める。lwIPのpbufとゼロコピー、MAC/PHYのDMA連携、割込みとポーリングの選択、UDP・CoAP・MQTTの軽量プロトコル判断まで、制約下の設計を原理から見通せる。

応用組込みTCP/IPlwIPネットワークゼロコピーDMA最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.組込みTCP/IPはRAMとCPUの制約が主敵。lwIPは数十KB級で動くよう、pbufチェーンとゼロコピー、静的メモリプールで確保のばらつきとコピーコストを削る。
  • 2.受信はMAC DMAがディスクリプタリングへフレームを書き、RX割込みでスタックへ渡す。ゼロコピーではDMAバッファをそのままpbufとして上位へ通し、memcpyを避ける。
  • 3.スレッド無しのraw/callback APIか、RTOS上のsocket風NETCONN/BSD APIかで実装が分岐。用途に応じTCPよりUDP・CoAP・MQTT-SNなど軽量プロトコルを選ぶのが定石。

PCのスタックはなぜそのまま載らないのか

Linux や Windows の TCP/IP スタックは、潤沢な RAM と MMU、動的メモリ確保を当然の前提に設計されています。ソケットバッファは接続ごとに数十〜数百 KB を割り当て、受信データは NIC バッファからカーネルバッファ、さらにユーザ空間へと何度もコピーされます。この贅沢は、SRAM が数十 KB しかないマイコンでは即座に破綻します。組込み TCP/IP スタックの設計課題は、突き詰めれば 限られた RAM と CPU サイクルで、いかにプロトコルの正しさを保ちながら資源浪費を削るか に集約されます。

代表格が lwIP(lightweight IP)です。数十 KB の ROM と 10〜40 KB 程度の RAM で TCP/UDP/IP/ICMP/DHCP/DNS を動かせるよう設計され、確保のばらつき・コピー回数・スレッド依存という 3 つのコストを徹底的に抑えます。以下ではこの 3 点を軸に、内部動作を原理から解きます。

pbufとゼロコピー:コピーを減らす中核

スタックの心臓は、パケットデータをどう保持するかです。lwIP は pbuf(packet buffer) という単位でこれを表現します。1 つのパケットが 1 個の連続バッファに収まるとは限らないため、pbuf は チェーン(連結リスト) を組めます。ヘッダ部と本体、あるいは分割された断片を別々の pbuf として繋ぎ、論理的に 1 パケットとして扱う——これが可変長データを固定サイズの断片で扱う要です。

pbuf には確保元の異なる型があり、ここにゼロコピー設計の勘所が現れます。

pbufの型データの実体用途と狙い
PBUF_RAMヘッダ+ペイロードを連続確保送信データの組み立て。1回の確保で完結させコピーを抑える
PBUF_POOL固定サイズプールから複数連結受信の主役。確保時間が一定で断片化しない
PBUF_ROM / PBUF_REF実体は別領域を参照(ヘッダのみ確保)ROM上の定数やDMAバッファを指す。コピーせず送受信するゼロコピーの鍵

ゼロコピーとは、データを物理的に複製せず、参照(ポインタ)の付け替えだけで層をまたいで受け渡す技法です。受信で言えば、MAC の DMA が書き込んだフレーム領域をコピーして pbuf を作るのではなく、その領域を指す pbuf をそのまま上位へ通します。送信なら、アプリのバッファを PBUF_REF で参照し、コピーせずに MAC の送信ディスクリプタへ渡します。コピー 1 回は「CPU がバイト数ぶんのロード・ストアを回す」ことに等しく、スループットが上がるほどこの負荷は無視できません。ゼロコピーはこれを原理的にゼロへ近づけます。

ゼロコピーの代償:バッファの所有権と寿命

参照で渡すということは、実体バッファの寿命を送受信完了まで延ばす責任が生じることです。送信をゼロコピーで行う場合、PBUF_REF が指すアプリのバッファは、MAC が送信を終える(=TX完了割込みが来る)まで書き換えてはいけません。早く再利用すると、まだ送られていないデータを壊します。受信 DMA バッファをそのまま上位へ渡す設計でも、そのバッファをリングへ返す前にアプリが処理を終えている保証が要ります。ゼロコピーの難所はコピー削減そのものより、この所有権と解放タイミングの管理にあります。

メモリ管理:mallocを避ける理由

組込みスタックは汎用の malloc/free を嫌います。理由は 2 つ。第一に 確保時間が非決定的 で、ヒープの状態次第で数百サイクル変動し得ること。パケット到着ごとに揺らぐ確保時間は、リアルタイム性(/embedded/real-time-wcet/ の WCET 解析)を崩します。第二に フラグメンテーション——長時間の確保・解放の繰り返しでヒープが虫食いになり、総空きは足りるのに連続領域が取れず確保失敗する現象です。稼働し続ける組込み機器では致命的です。

そこで lwIP は既定で 静的メモリプール を使います。起動時に「pbuf 用に N 個」「TCP PCB 用に M 個」といった固定数の枠を確保し、実行中はそこから枠を貸し借りするだけにします。確保・解放が O(1) で時間が一定になり、断片化も起きません。代償は、プール数を使い切ると新規確保が失敗する(=設計時にサイジングが要る)ことです。MEMP_NUM_TCP_PCBPBUF_POOL_SIZE といったコンパイル時定数の見積りが、そのまま同時接続数や受信バーストの耐性を決めます。

MAC/PHYとの接続:フレームはどこから来るか

TCP/IP スタックの下端はイーサネット MAC に繋がります。ここの構造を押さえないと、受信経路は理解できません。

[受信データの流れ]

  ケーブル
    │  差動信号
    ▼
  PHY  ── アナログ信号を送受信、4B/5B+MLT-3等の物理層符号化(100BASE-TX)
    │  MII / RMII / RGMII (データ+クロック)
    ▼
  MAC  ── フレーム境界検出・CRC検査・アドレスフィルタ
    │  DMA が受信フレームを RAM のディスクリプタリングへ書く
    ▼
  RXディスクリプタリング(複数バッファの循環配列)
    │  RX完了割込み
    ▼
  TCP/IPスタック(pbuf として取り出す)

PHY は物理層(アナログ信号・符号化・オートネゴシエーション)を担い、MAC はデータリンク層(フレーム構成・CRC・MAC アドレスフィルタ)を担います。両者は MII/RMII/RGMII といったインタフェースで結ばれ、MAC の設定レジスタ(速度・全二重の反映)は SMI/MDIO という別系統のシリアルバスで PHY を読み書きして行います。

肝は、MAC がフレームを DMA で RAM のディスクリプタリングへ直接書く ことです。ディスクリプタとは「このバッファはどこにあり、何バイトで、所有者は CPU か DMA か」を記す小さな構造体で、それを環状に並べたのが RX リングです。フレームが 1 つ入るたびに DMA が空きバッファへ書き込み、所有権フラグを CPU へ渡し、RX 割込みを上げます。この DMA 連携こそが、CPU にバイトコピーをさせずにフレームを取り込む仕組みです(/embedded/dma-transfers/ の非対称アドレス制御と完了割込みが、そのまま MAC でも働きます)。

ゼロコピー受信はディスクリプタとpbufを一体化する

高効率な実装では、RX ディスクリプタが指すバッファ自体を pbuf の実体にします。DMA が書いたその領域を PBUF_POOL/参照 pbuf として上位へ渡し、アプリが処理を終えたらそのバッファを空きとしてリングへ返す。こうすると「DMA バッファ → pbuf」のコピーが完全に消えます。ただしプール枯渇への備えが要ります。上位が滞留してバッファを返さないと、リングに空きがなくなり以降のフレームを取りこぼす(オーバーラン)ため、フロー制御やドロップ方針の設計が伴います。

割込みとポーリング:いつスタックを動かすか

受信フレームをスタックに処理させる駆動方式は 2 つあり、この選択がアーキテクチャ全体を左右します。

方式動作向く状況・弱点
割込み駆動RX完了割込みで即時に処理を起動低遅延。ただし高負荷時は割込み過多でCPUが飽和しやすい
ポーリング定期的にリングを見て溜まったフレームを処理高スループット時に有利。低負荷では無駄なCPU消費と遅延増
割込み→タスク委譲ISRは通知のみ、実処理はタスクで(ボトム半分)RTOS構成の定石。ISRを短く保ち処理を並べ替え可能にする

素朴な設計では RX 割込みハンドラ内でスタック処理まで走らせがちですが、これは危険です。プロトコル処理は長く、その間ほかの割込みが抑止されます。定石は ISR を「フレームが来た」通知だけに切り詰め、実際の pbuf 取り出しとプロトコル処理はスタック用タスク(またはメインループ)へ委譲 することです(/embedded/interrupt-handling-isr/ のトップ半分/ボトム半分の分割がそのまま当てはまります)。

lwIPのスレッド安全性:コア関数を割込みから直接呼ばない

lwIP のコア API(raw/callback API)は再入可能ではありません。割込みハンドラからスタックのコア関数を直接呼ぶと、メインの処理と競合して内部状態を壊します。ISR で受信を検知したら、フラグやセマフォ、あるいは tcpip_input() を介したメッセージ投函でスタックのコンテキストへ処理を渡すのが正しい作法です。ベアメタルの NO_SYS=1 構成では、割込みで立てたフラグをメインループが sys_check_timeouts() と併せて拾う形にします。スレッド安全性の境界を破ると、再現困難なクラッシュの温床になります。

2つの実行モデルとAPI

lwIP は動作環境に応じて 2 つの構成を取ります。NO_SYS=1(OSなし) は RTOS を前提とせず、単一のメインループから raw/callback API を叩きます。受信やタイムアウトはコールバックで通知され、ブロッキングは一切ありません。フットプリントは最小ですが、アプリはイベント駆動で書く必要があります。一方 NO_SYS=0(OSあり) は RTOS 上で専用の TCP/IP タスクを回し、NETCONN API や BSD ソケット互換 API を提供します。recv() のようにブロックできて記述は素直ですが、タスク・キュー・セマフォのぶん RAM を食います。RTOS の有無は /embedded/embedded-linux-vs-rtos/ の判断軸と地続きです。

軽量プロトコルの選択:TCPが常に正解ではない

制約下では、上位プロトコルの選定そのものが最適化になります。TCP は再送・順序保証・輻輳制御・フロー制御を備える代わりに、コネクション状態(PCB)、送信済み未確認データの再送バッファ、各種タイマを接続ごとに抱え、RAM と複雑さを消費します。

プロトコル特徴組込みでの位置づけ
TCP信頼性・順序・輻輳制御を内蔵。状態とバッファが重い設定転送やファーム更新など確実性が要る場面に限定
UDPコネクションレスで最小。信頼性は自前センサ値の周期送信など、多少の欠落を許せるテレメトリ向き
CoAPUDP上のREST風。任意の再送・確認応答を軽量に制約機器のRESTful IoT。HTTPの重さを避けたい用途
MQTT / MQTT-SNpublish/subscribe。SN版はUDPで更に軽量多数デバイスのイベント収集。ブローカ経由の疎結合

判断の軸は明快です。欠落や順序乱れが許されず、かつ低頻度ならば TCP の信頼性が割に合います。周期的で多少の取りこぼしを上位で吸収でき、RAM を切り詰めたいならば UDP を基礎に、必要な信頼性だけ CoAP の確認応答(CON メッセージ)や MQTT-SN の QoS で足すのが効率的です。「信頼性は欲しいが TCP はフルには要らない」領域を、UDP+軽量な再送で埋めるのがこの層の設計術です。低消費電力機器では、TCP の常時接続とキープアライブが /embedded/low-power-sleep-modes/ の深いスリープと相性が悪く、この一点だけでも UDP ベースが選ばれることがあります。

資格・面接で問われる勘どころ

「組込みTCP/IPで RAM を抑える工夫は」には『pbuf のチェーンとゼロコピー、静的メモリプールによる固定時間・無断片化の確保』。「ゼロコピーの難点は」には『データ複製は消えるが、参照バッファの所有権と解放タイミングの管理が必要になる』。「受信でMACはどう動くか」には『DMAでフレームをRXディスクリプタリングへ書き、RX割込みで通知、スタックがpbufとして取り出す』。「割込みハンドラでスタックを直接処理しない理由」には『コアAPIが再入不可で、割込み抑止も長引くため、ISRは通知に留めタスクへ委譲する』と答えられれば要点を押さえたことになります。

まとめ

組込み TCP/IP スタックは、PC のスタックから「潤沢な RAM」という前提を外し、制約の中でプロトコルの正しさを保つための設計の集合体です。pbuf のチェーンで可変長データを固定断片として扱い、ゼロコピーと静的プールでコピーと確保のばらつきを削り、MAC の DMA とディスクリプタリングでフレームを CPU 非介在で取り込み、割込みは通知に徹してタスクへ処理を委ねる——この骨格が lwIP をはじめとする軽量スタックの核心です。そして上位では、TCP を万能視せず UDP や CoAP・MQTT-SN を用途で選ぶことが、RAM と消費電力の両面で効いてきます。組込みネットワークは「機能を足す」より「無駄を削って所有権を管理する」設計だと捉えると、実装もデバッグも一本の筋で見通せます。

組込み・IoT Article

組込みTCP/IPスタックを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

組込み

比較で見る軸

難易度: advanced / カテゴリ: 組込み・IoT / タグ数: 6

導入後に効く点

受信はMAC DMAがディスクリプタリングへフレームを書き、RX割込みでスタックへ渡す。ゼロコピーではDMAバッファをそのままpbufとして上位へ通し、memcpyを避ける。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
組込み・IoT
タグ数
6

判断チェックリスト

  • 自社の用途が「組込み / TCP/IP」に近いか確認する。
  • 強みである「組込みTCP/IPはRAMとCPUの制約が主敵。lwIPは数十KB級で動くよう、pbufチェーンとゼロコピー、静的メモリプールで確保のばらつきとコピーコストを削る。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

組込みTCP/IPlwIPネットワークゼロコピー組込みTCP/IPlwIP