1

libpcap を使用してパケットをキャプチャします。パケットが利用可能になったらすぐに、パケットを FIFO キューに入れる必要があります。ただし、FIFO キューは 2 つのスレッドで共有され、1 つのスレッドが pcap_next() を呼び出し、パケットを FIFO キューに入れます。別のスレッドが fifo キューからパケットをフェッチします。したがって、それをミューテックスに関連付ける必要があります。以下のように:

u_char* pkt;
for(;;){
    pkt = pcap_next();
    lock(&mutex);
    some_process(pkt);
    insert(pkt, list);
    unlock(&mutext);
 }

pcap_next() はパケット バッファに関連しています。バッファにパケットがない場合、pcap_next() はブロックされます。パケットがある場合、pcap_next() の呼び出しごとに 1 パケットが返されます。

ロックとロック解除の操作ペアごとに 1 つのパケットしかフェッチできません。パケットの到着が頻繁でなければ問題ありません。しかし、バッファ内に多くの保留中のパケットがあるように、パケットの到着が頻繁にある場合、1 つのパケットに対してロックとロック解除の操作ペアを実行するのは少しリソースを消費します。

私が望んでいるのは、パケットを処理して挿入した後、すぐにパケット バッファに利用可能なパケットがあるかどうかを確認できることです。ある場合は、処理と挿入を続行します。それ以外の場合は、ミューテックスのロックを解除してループに戻ります。

これに対する回避策はありますか?

4

2 に答える 2

1

次のようなものを試してください

/*
 * XXX - this can fail on some platforms and with some devices,
 * and there may be issues with select() on this.  See the
 * pcap_get_selectable_fd() man page for details.
 */
pcap_fd = pcap_get_selectable_fd(p);
pcap_setnonblock(p);  /* XXX - check for failure */

for (;;) {
    fd_set fdset;
    struct timeval timeout;

    /*
     * Wait for a batch of packets to be available.
     */
    FD_ZERO(&fdset);
    FD_SET(pcap_fd, &fdset);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    if (select(1, &fdset, NULL, NULL, &timeout) == -1) {
        report an error;
    } else {
        lock(&mutex);
        pcap_dispatch(p, -1, callback, pointer-to-stuff);
        unlock(&mutex);
    }
}

このようにして、mutex をロックし、パケットのバッチ全体を処理してから、mutex のロックを解除します。多くの OS キャプチャ メカニズムは、バッチで複数のパケットを配信するため、この場合、バッチごとに 1 つのロック/ロック解除のペアが存在します。

コールバックは、などを行いsome_process(pkt);ますinsert(pkt, list);

バッチの処理が完了すると、次のバッチがすぐに利用可能になる可能性があるため、これはロック/ロック解除のペアの絶対的な最小値を達成しません。ただし、絶対最小値では、他のスレッドがかなりの期間ロックアウトされて、まったく進行できなくなる可能性があるため、バッチごとにロックおよびロック解除するのが最適な場合があります。

于 2015-03-26T21:07:16.473 に答える
0

pcap_dispatch() を使用するか、ノンブロッキング スタイルの pcap_next() で select() を使用します。

于 2013-05-14T16:22:52.147 に答える