0

libevent を使用してネットワーク プログラムのプログラミングを行っています。

このプログラムでは、libpcap を使用してパケットをキャプチャし、これらのパケットを変更してから送信します。これらの手順はリアルタイムで行う必要があります。

そこで、ライブ キャプチャを作成し、pcap_get_selectable_fd を使用してライブ キャプチャのファイル記述子を取得し、libevent ループにpcap_fdREAD_EV イベントを追加します。pcap_fdとにかく、ファイル記述子をポーリングする select() または epoll() のようなものです。

しかし、プログラムが期待どおりに動作しないことに気付いたので、tcpdump といくつかのデバッグ ログを使用して問題を確認します。ポーリングpcap_fdが正しく機能しないことがあります。たとえば、最初は正常に機能しているように見えます。しばらくして、 の READ_EV イベントpcap_fdが 2 秒後にトリガーされますが、これは実際には大きな遅延です。

マニュアルを読んだところ、次のように書かれています。

   pcap_get_selectable_fd(3) will return a file descriptor. But simple select() 
   or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer's worth of packets is received, even if the read
   timeout expires before then.  

ライブ キャプチャは約 15 パケット (それぞれが 66 バイト) をキャプチャしたようですが、READ_EV イベントは 2 秒後までトリガーされません。しかし、最初は 1 つのパケットの到着でも READ_EV イベントをトリガーできます。これは非常に不安定であることを意味します。

   To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non-blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.

私の質問は上記の段落です。

1 タイムアウトには、読み取りタイムアウトと自分で定義したタイムアウトの 2 つがあるようですが、読み取りタイムアウトとは何ですか?

pcap_next()2 非常に短いタイムアウトを設定し、またはを使用してライブ キャプチャをポーリングする必要があるように思えますが、そうpcap_dispatchですか? 私のポーリングは非常にCPUを消費する可能性がありますか?

ありがとう!</p>

4

1 に答える 1

1

問題の段落はおそらく

ほとんどの BSD (Mac OS X を含む) のほとんどのバージョンでは、select() と poll() は BPF デバイスでは正しく機能しないことに注意してください。pcap_get_selectable_fd() は、これらのバージョンのほとんど (FreeBSD 4.3 と 4.4 を除く) でファイル記述子を返します。単純な select() または poll() は、pcap_open_live() で指定されたタイムアウトが期限切れになった後でも返されません。これを回避するには、select() または poll() を使用してパケットの到着を待機するアプリケーションは、pcap_t を非ブロック モードにし、select() または poll() のタイムアウトがpcap_open_live() で指定されたタイムアウトに等しく、そのタイムアウトが期限切れになった後にパケットを読み取ろうとする必要があります。select() または poll() が pcap_t のファイル記述子を読み取る準備ができていることを示したかどうかに関係なく。(この回避策は FreeBSD 4.3 以降では機能しませんが、FreeBSD 4.6 以降では select() と poll() が BPF デバイスで正しく動作するため、害はありませんが回避策は必要ありません。)

ここで重要な最初の文を引用しませんでした-Linuxシステムコールである「epoll()」と言いました。その段落は Linux には適用されません。

(pcap_get_selectable_fd man ページにあるその段落の現在のバージョンは、

   Note that in:

          FreeBSD prior to FreeBSD 4.6;

          NetBSD prior to NetBSD 3.0;

          OpenBSD prior to OpenBSD 2.4;

          Mac OS X prior to Mac OS X 10.7;

   select()   and   poll()   do   not   work  correctly  on  BPF  devices;
   pcap_get_selectable_fd() will return a file descriptor on most of those
   versions  (the  exceptions  being  FreeBSD  4.3  and 4.4), but a simple
   select() or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer’s worth of packets is received, even if the read
   timeout expires before then.  To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non‐blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.  (That workaround will not work in FreeBSD 4.3
   and  later; however, in FreeBSD 4.6 and later, select() and poll() work
   correctly on BPF devices, so the workaround isn’t  necessary,  although
   it does no harm.)

どちらがより正しいです。ただし、Mac OS X 10.6 の BPF のバグにより、ノンブロッキング モードが正しく機能しないため、この回避策も OS X 10.6 では機能しないことに注意してください。10.7 以降では必要ありません。)

libevent を使用している場合は、( NOT an !)pcap_fdを使用して を非ブロッキング モードにし、イベントを取得した場合は を使用してパケットを処理する必要があります。pcap_setnonblock()fcntl()READ_EVpcap_dispatch()

于 2013-11-07T12:32:18.003 に答える