在 Linux Mint(17 或 17.1)上,我使用 tcpdump 通过以下命令捕获一些数据包:
tcpdump -UnvXSs 4096 -B 1024 -i eth0
尽管有 -U 选项,但它实际上并不会立即输出数据包。相反,它们几乎每秒被保存和输出一次,唯一的例外是,如果我引起大量网络活动,它们会更频繁地输出。我也尝试了 -l 选项,它没有什么区别。使用较小的缓冲区(-B 参数)使得较少的流量可以导致更频繁的输出,但最小的可能是 128,它仍然足够大,我想要看到的流量每秒只输出一次。
我在 tcpdump 上运行 strace。它反复在以下行暂停:
poll([{fd=3, events=POLLIN}], 1, 1000) = 1 ([{fd=3, revents=POLLIN}])
它在那里停留 1 秒,然后恢复,输出更多数据包,然后返回到 poll() 调用。
在这些 poll() 调用发生之前返回 3 的最后一个系统调用是:
socket(PF_PACKET, SOCK_RAW, 768) = 3
在这些对 poll() 的调用之间,除了 write() 调用之外什么都没有,因此不会因 DNS 查找或其他任何事情而延迟。
所以我得出的结论是 tcpdump 每秒只显示一次数据包的原因是因为内核传递数据包的频率是一样的。
如何让它在内核收到数据包后立即输出数据包?
Linux version 3.13.0-24-generic (buildd@batsu) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014
答案1
所以我得出的结论是 tcpdump 每秒只显示一次数据包的原因是因为内核传递数据包的频率是一样的。
pcap_open_live()
是 - 当 tcpdump 使用或 使用pcap_create()
and打开捕获设备时pcap_activate()
,它指定 1 秒的超时。这意味着,在许多操作系统(包括具有较新版本内核和 libpcap 的 Linux 发行版,以及 *BSD、OS X 和 Solaris)上,内核将缓冲数据包,直到其缓冲区填满或 1 秒已满。已过去,并将传递整个缓冲区的数据包,以提高效率。
较新版本的 tcpdump 将在打印数据包时禁用该缓冲,而不是将它们以二进制形式保存到文件中。
如何让它在内核收到数据包后立即输出数据包?
运行较新版本的 tcpdump,或修改 tcpdump 以指定更短的超时或完全禁用超时。