8

lwipという TCP/IP スタックを使用しています。データ パケットを受信する同様のコールバック関数から着想を得て、データ パケットを送信する以下の関数を実装しました。

パケットを受信するたびに、pbuf_alloc関数を使用してバッファーを作成します。次に、 を使用してパケットを送信しudp_sendtoます。最後に、 を使用してバッファを解放しpbuf_freeます。(以下のコードを参照してください。)

何らかの理由でpbuf_free、バッファを解放していません。n(パケットの後にバッファ オーバーフローが発生しますn。 はプール サイズです。) lwip wikiは次のように警告しています。

また、ネットワーク ドライバは、pbuf_free を呼び出すときに、pbuf メモリが実際に解放されていると想定しない場合があります。

pbuf_freeバッファを強制的に解放するにはどうすればよいですか? バッファオーバーフローはどのように回避されますか?

(以下の私の実装。)

static err_t IAP_tftp_send_data_packet(struct udp_pcb *upcb, struct ip_addr *to, int to_port, int block)
{
  err_t err;
  struct pbuf *pkt_buf;
  char packet[TFTP_DATA_PKT_LEN_MAX];
  int bytesRead;
  int bytesToSend;

  /* Specify that we are sending data. */
  IAP_tftp_set_opcode(packet, TFTP_DATA); 

  /* Specify the block number that we are sending. */
  IAP_tftp_set_block(packet, block);

  bytesRead = IAP_tftp_set_data(packet, block);

  if(bytesRead != 0) {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1);
  } else {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512;
  }

  pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);

  if (!pkt_buf)
  {
    print("(TFTP) Buffer overflow!\r\n");
  }

  /* Copy the file data onto pkt_buf. */
  memcpy(pkt_buf->payload, packet, bytesToSend);

  err = udp_sendto(upcb, pkt_buf, to, to_port);

  /* free the buffer pbuf */
  printf("%d\n\r", pbuf_free(pkt_buf));

  return err;
}
4

4 に答える 4

7

どのバージョンの lwIP を使用していますか? 異なるバージョンに応じて、答えは大きく異なります。

pbuf_alloc() 内で呼び出された memp_malloc() 割り当て関数が失敗したか、pbufs チェーンが失敗したため、NULL を返します。

pbuf_alloc() は、渡された引数にも NULL が含まれている場合、NULL を返します (NULL 引数チェックのため)。

新しいバージョンでは、MEMP_OVERFLOW_CHECK マクロに含まれる値を示していただけますか? マクロ値 >= 2 の場合、lwIP は異なる動作を示します。

また、別の原因として、マルチスレッドを使用している場合、pbuf_alloc() 内のロック メカニズムが失敗し、NULL が返される可能性があります。

一部のバージョンでは、pbuf_alloc() を呼び出す前に、pbuf_init() を呼び出す必要があります。

これを試すことができます:

pkt_buf = NULL;//Use NULL, just incase the NULL is not 0 as per your compiler.
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_REF);
if(pkt_buf == NULL)
{
   printf("pbuf_alloc failed.\n");
}
else
{
   /* Do something with the allocated pbufs and free it. */
}

PBUF_REF は、pbuf にバッファ メモリを割り当てません。pbuf は単一のスレッドでのみ使用する必要があり、pbuf がキューに入れられた場合は、pbuf_take を呼び出してバッファーをコピーする必要があります。

RAM にバッファを割り当てる PBUF_RAM を試すこともできます。

詳細については、使用している lwIP のバージョンのソース ファイルを参照することもできます。

于 2012-07-23T12:10:34.993 に答える
6

最も簡単な解決策は、 buffer を作成することですstatic。つまり、呼び出しごとに同じバッファーを再利用します。

static struct pbuf *pkt_buf = NULL;

if( pkt_buf == NULL )
    pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);
if( pkt_buf == NULL )
{
    print("(TFTP) Buffer overflow!\r\n");
}

シナリオにドライバーのアンロード/再ロードが含まれる場合、メモリ リークが発生します。これを修正するには、IAP_tftp_send_data_packet()関数の外側でバッファーを静的pbuf_free()にし、ドライバーがアンロードされたときに呼び出します (lwip が通知すると仮定します)。

于 2012-06-18T13:40:27.633 に答える