Ich schreibe ziemlich einfach pcap "live" Capture Engine, aber die Paketverarbeitung Callback-Implementierung für pcap_dispatch sollte relativ lange Zeit für die Verarbeitung dauern. Läuft pcap jeden "pcap_handler" Callback in einem separaten Thread? Wenn ja, ist "pcap_handler" threadsicher, oder sollte Vorsicht geboten sein, um kritische Abschnitte zu schützen? Oder, funktioniert pcap_dispatch Callback seriell? Z.B. ist "pcap_handler" für das Paket 2 nur aufgerufen, nachdem "pcap_handler" für Paket 1 fertig ist? Wenn ja, gibt es einen Ansatz, um Latenz zu vermeiden? Vielen Dank, -V
Pcap funktioniert grundsätzlich so: Es gibt einen Kernel-Mode-Treiber, der die Pakete erfasst und sie in einen Puffer der Größe B legt. Die Anwendung im Benutzermodus kann jederzeit eine beliebige Anzahl von Paketen anfordern, indem sie pcap_loop
, pcap_dispatch
oder pcap_next
verwendet (letzteres ist im Grunde pcap_dispatch
mit einem Paket).
Wenn Sie also pcap_dispatch
verwenden, um einige Pakete anzufordern, geht libpcap zum Kernel und fragt nach dem nächsten Paket im Puffer (Wenn es keinen gibt, den Timeout-Code und Stuff-Kicks in, aber dies ist für diese Diskussion irrelevant), überträgt es in das Benutzerland und löscht es aus dem Puffer. Danach ruft pcap_dispatch
den Handler auf, reduziert den pakete-zu-tun -Zähler und beginnt von vorne. Daher kehrt pcap_dispatch
nur zurück, wenn die angeforderte Menge an Paketen verarbeitet wurde, ein Fehler aufgetreten ist oder ein Timeout aufgetreten ist.
Wie Sie sehen, ist libpcap vollständig ohne Threading, wie die meisten C-APIs. Der Kernel-Modus-Treiber ist jedoch offensichtlich glücklich genug, Pakete an mehrere Threads zu liefern (sonst könnten Sie nicht aus mehr als einem Prozess erfassen) und ist vollständig Thread-sicher (es gibt einen separaten Puffer für jeden Benutzermodus handle).
Dies bedeutet, dass Sie alle Parallelismen selbst implementieren müssen. Du solltest so etwas tun:
%Vor% Beachten Sie, dass wir das Paket in den Heap kopieren müssen, da die Zeiger header
und data
ungültig sind, nachdem der Callback zurückkehrt.
Die Funktion queue_work_item
sollte einen Worker-Thread finden und ihm die Aufgabe zuweisen, das Paket zu bearbeiten. Da Sie angegeben haben, dass der Rückruf relativ lange dauert, benötigen Sie wahrscheinlich eine große Anzahl von Worker-Threads. Die Suche nach einer geeigneten Anzahl von Arbeitern unterliegt einer Feinabstimmung.
Am Anfang dieses Posts habe ich gesagt, dass der Kernel-Mode-Treiber einen Puffer hat, um eingehende Pakete zu sammeln, die auf die Verarbeitung warten. Die Größe dieses Puffers ist implementierungsdefiniert. Der Parameter snaplen
auf pcap_open_live
steuert nur, wie viele Bytes eines Pakets erfasst werden. Die Anzahl der Pakete kann jedoch nicht auf tragbare Weise gesteuert werden. Es könnte eine feste Größe sein. Es kann größer werden, wenn mehr und mehr Pakete ankommen. Wenn jedoch if überläuft, werden alle weiteren Pakete verworfen, bis genug Platz für den nächsten ist. Wenn Sie Ihre Anwendung in einer Umgebung mit hohem Datenverkehr verwenden möchten, sollten Sie sicherstellen, dass Ihr * pcap_dispatch * -Rückruf schnell ausgeführt wird. Bei meinem Beispiel-Callback wird das Paket einfach einem Worker zugewiesen, sodass es auch in Umgebungen mit hohem Datenverkehr gut funktioniert.
Ich hoffe, dies beantwortet alle Ihre Fragen.
Tags und Links libpcap