pcap在Unix系统中的缓冲工作原理是什么?

13
假定情景: 一个UDP数据流到达机器X,该机器同时运行两个程序,其中一个使用recv()监听数据包,另一个正在运行pcap。
在这种情况下,据我所知,数据包存储在接口中,直到内核轮询该接口,然后将它们移动到内核内存中的缓冲区,并将数据包复制到另外两个缓冲区 - 一个用于使用recv监听的程序,另一个用于使用pcap监听的程序。当数据包被读取时,它们会从各自的缓冲区中删除 - 可以通过pcap_next()或recv()读取,或者下次进程调度程序运行它们时(我假设它们在这种情况下是阻塞的)。这样对吗?是否真的使用了4个缓冲区,还是有其他处理方式?
我想要一个尽可能详细的描述,描述涉及到哪些缓冲区,并且数据包如何从一个缓冲区移动到另一个缓冲区(例如,数据包在进入recv缓冲区之前、之后或未定义时是否会被复制到pcap缓冲区)。
我知道这似乎是一个大问题,但我真正关心的只是数据包存储在哪里,以及它在那里停留的时间有多长。简单列出要点即可。理想情况下,我希望得到一个通用的答案,但如果在不同的操作系统之间有所不同,我最感兴趣的是Linux。
1个回答

8

Linux案例(BSD可能会使用mbufs,而不是skbuffs):

Linux使用skbuffs(套接字缓冲区)来缓冲网络数据。 skbuff包含一些关于某些网络数据的元数据和指向该数据的指针。

抓包工具(pcap用户)创建skbuff的克隆。克隆是一个新的skbuff,但它指向相同的数据。当有多个skbuff(原始skbuff及其克隆体)共享需要修改的数据时,它首先需要创建一个新的副本(写时复制)。

当不再需要一个skbuff时,它用kfree_skb()释放它。 kfree_skb()减少引用计数,当该引用计数达到零时,skbuff被释放。这对于克隆体稍微复杂一些,但这是大致的想法。


那么,您的意思是recv()函数使用内核缓冲区,但每个pcap实例都有自己的缓冲区副本?这些克隆是在什么阶段进行的 - 在接收数据包时?当pcap想要读取它时? - Benubird
每个pcap实例都有自己的元数据副本,但它们共享相同的数据。克隆是在接收数据包时进行的(在skb_deliver()中如果我没记错的话)。 - ninjalj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接