yfr*_*com 4 c linux packet-sniffers libpcap
如果我想在 Linux 中嗅探数据包而不设置任何过滤器,我看到了 2 个选项。
使用libpcap
自己使用原始套接字,例如https://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
为什么libpcap比我自己使用原始套接字更好?
三个原因:
1)正确设置更容易。
2) 它是可移植的,甚至可以移植到 Windows,它使用非常相似但不同的套接字 API。
3)速度快得多。
1和2,IMO,不需要太多解释。我将深入探讨3。
要理解为什么 libpcap(通常)更快,我们需要了解套接字 API 中的瓶颈。
libpcap 倾向于避免的两个最大瓶颈是系统调用和副本。
它如何做到这一点是特定于平台的。
我将讲述 Linux 的故事。
Linux 从 2.0 IIRC 开始,实现了所谓的 AF_PACKET 套接字系列,后来又实现了 PACKET_MMAP。我不太记得前者的好处,但后者对于避免从内核复制到用户空间(内核端仍然有一些副本)和系统调用至关重要。
在 PACKET_MMAP 中,您在用户空间中分配一个大的环形缓冲区,然后将其关联到 AF_PACKET 套接字。该环形缓冲区将包含一些元数据(最重要的是,一个标记,表明某个区域是否已准备好供用户处理)和数据包内容。
当数据包到达相关接口(通常是您将套接字绑定到的接口)时,内核会在环形缓冲区中创建一个副本,并将该位置标记为可供用户空间*使用。如果应用程序正在等待套接字,则会收到通知*。
那么,为什么这比原始套接字更好呢?因为在设置套接字后,您可以使用很少或没有系统调用,具体取决于您是要忙轮询缓冲区本身还是等待poll几个数据包准备好,并且因为您不需要来自套接字内部的副本RX 缓冲区到您的用户缓冲区,因为它与您共享。
libpcap 会为您完成所有这些工作。并且可以在 Mac、*BSD 以及几乎任何为您提供更快捕获方法的平台上执行此操作。
*版本 3 有点复杂,粒度是“块”而不是数据包。